在C语言中修饰词(限定符)包括:const、static、volatile、register、extern、restrict、inline、auto......等等。
1.const----只读,不可更改。const右边是谁,谁就不能更改
// 1. 普通只读变量 const int a = 10; a = 20; // 报错,不能修改 // 2. 指针常量:指针本身不可改,指向内容可改 int *const p; //p不能更改(地址固定),*p能改 // 3. 常量指针:指向内容不可改,指针可改 const int *p; //*p不能更改(内容只读),p能改 int const *p; //*p不能更改(内容只读),p能改 // 4. 指针和内容都不可改 const int *const p;2.static静态修饰,修饰局部变量、修饰全局变量/函数
修饰局部变量:
void fun(void) { static int i = 0; i++; }整个程序运行全程不随函数调用销毁;只初始化一次;值会保留上次调用结果;存放在全局数据区,不占用栈空间。
修饰全局变量、函数:
static int g_val; static void Delay(void);作用域仅限当前文本,其他 .c 文件无法访问;实现模块私有化,代码封装。
3.volatile----易变变量,禁止编译器优化
告诉编译器这个变量值可能被外部变量改变,禁止优化,不要缓存,每次都从内存真实读取。
用法:中断里修改的,在主循环读取的全局变量;硬件寄存器;多线程共享的变量;DMA改变的变量。
// 中断会改这个标志 volatile uint8_t flag = 0; // 寄存器映射 必须加volatile #define PORTA (*((volatile uint8_t *)0x40000000))4.extern外部声明
声明外部变量、函数,告诉编译器这个东西在别的文件或别处定义。多文件共享全局变量、调用其他.c文件的函数,只声明不定义,防止重复定义报错。
// 声明外部全局变量 extern int g_num; // 声明外部函数 extern void Uart_Init(void);5.register----寄存器变量,放进寄存器
建议编译器把变量放到寄存器中,不占内存,访问速度快。
6.restrict某个指针是指向这块内存的唯一访问者,编译器可做强力优化,提升速度。
常用在memcpy、strcpy、DMA、高速数据处理、算法等中。
7.inline----内联函数
编译时把函数代码直接「原地嵌入」调用处,省去函数调用的跳转、压栈、出栈开销,提速、省开销。
static inline int Max(int a, int b) { return a > b ? a : b; }对比:宏 vs inline 函数
// 宏:无类型检查、容易出bug #define MAX(a,b) ((a)>(b)?(a):(b)) // 内联函数:有类型检查、安全、一样快 static inline int Max(int a, int b) { return a > b ? a : b; }8._Alignas和_Alignof----内存对齐
C11 标准关键字,内存对齐专用,单片机、STM32、结构体、联合体、DMA 高频必用(DMA 必须用这个,否则硬件不工作)。
_Alignof(T):查询类型 T 默认需要几字节对齐(查规则)。
_Alignas(N):强制变量 / 结构体按 N 字节对齐(改规则)。
嵌入式核心用途:DMA 缓冲区对齐、结构体协议布局、避免硬件访问异常
_Alignof(类型)#include <stdio.h> int main(void) { // 获取各类型默认对齐值 printf("char : %zu\n", _Alignof(char)); // 1 printf("short : %zu\n", _Alignof(short)); // 2 printf("int : %zu\n", _Alignof(int)); // 4 printf("long long: %zu\n", _Alignof(long long));// 8 return 0; }_Alignas(对齐值) 类型 变量; _Alignas(对齐值) struct xxx { ... };// 强制 x 4字节对齐 _Alignas(4) int x; // 强制 y 8字节对齐 _Alignas(8) int y; // 整个结构体强制 16 字节对齐 _Alignas(16) struct Msg { int a; char b; }; //STM32、单片机 DMA 缓冲区必须 4 字节 / 8 字节对齐,否则 DMA 传输乱数、死机 // DMA 缓冲区强制 4 字节对齐 _Alignas(4) uint8_t dma_buf[128];//组合用法 // 让 buf 按 int 的默认对齐值对齐 _Alignas(_Alignof(int)) uint8_t buf[64];// 默认按 int(4) 对齐 struct A { int x; char y; }; // 强制拉高到 16 字节对齐 _Alignas(16) struct B { int x; char y; };9.attribute系列,是 GCC/Clang 的编译器扩展(非 C 标准)
// 放在声明末尾、分号前;双括号、双下划线不可少 __attribute__((属性列表)) // 单属性 void func(void) __attribute__((noreturn)); int val __attribute__((aligned(16))); // 多属性(逗号分隔) void foo(void) __attribute__((unused, section(".mysec")));packed----取消结构体对齐,结构体紧凑排列
struct _attribute_((packed)) { char i; int j; };//大小是5,不是8 struct T { char a; int b; } __attribute__((packed)); // 总长度5字节(无填充) // 网络协议帧,必须紧凑无填充 struct Packet { uint8_t type; uint16_t len; uint32_t data; } __attribute__((packed)); // 大小:1+2+4=7字节(无填充) // 32字节对齐、紧凑排列,匹配硬件寄存器映射 struct Regs { uint32_t ctrl; uint32_t status; uint64_t data; } __attribute__((aligned(32), packed));unused----消除未使用警告
static void temp(void) __attribute__((unused)); // 定义了没调用也不告警