问题:static uint16 abc 和 uint16 abc 一样都是放在.bss段,那么static关键字到底起了什么作用?
它的核心作用不在于"放哪里",而在于"谁能看到它"和"活多久"。static有两个截然不同的应用场景,效果完全不同:
1. 文件作用域(全局静态变量)------ 隐藏变量
如果你在 .c 文件的最外层(所有函数之外)写下:
cpp
static uint16_t s_internalFlag;
作用:
-
限定作用域 :这个变量只能 在当前
.c文件中使用。即使其他.c文件用extern声明,也链接不到它。 -
防止命名冲突 :链接器不会将该符号导出到全局符号表。这在大型工程中极其重要------你可以放心地在不同文件中定义同名的
static全局变量,它们互不干扰。
对比不加 static(全局变量):
cpp
uint16_t g_internalFlag; // 默认是 "全局符号"
其他任何.c文件都可以通过extern uint16_t g_internalFlag; 来访问和修改它
2. 函数作用域(局部静态变量)------ 保持状态
如果你在函数内部写下:
cpp
void processSignal(void) {
static uint16_t s_callCount = 0;
s_callCount++;
// ...
}
作用:
-
生命周期变长 :虽然它写在函数内部,但不会 像普通局部变量那样分配在栈(Stack)上。它的内存固定在
.bss段,程序上电即存在,直到断电。 -
值会保持 :函数退出时,
s_callCount的值不会丢失。下次进入该函数时,它依然是上次退出时的值。 -
作用域受限 :虽然它在内存中常住,但其他函数无法 直接访问它,只有
processSignal内部能看到它。 -
也就是说第二次调用时,s_callCount 不会被初始化为 0,它会保留第一次调用后递增的值(即 1)。
对比普通局部变量(不加 static):
cpp
void processSignal(void) {
uint16_t callCount = 0; // 每次进入函数都分配在栈上,并初始化为 0
callCount++; // 退出后销毁,永远等于 1
}