static 可用于局部变量、全局变量与函数,主要作用是控制存储期或链接属性(可见范围)。本节说明 static 局部变量与文件作用域内的 static 全局对象、函数;更完整的存储类说明见存储类一章。
static 局部变量
普通局部变量在进入函数时创建、离开函数时销毁。带 static 的局部变量在程序启动时分配存储,只初始化一次,之后每次进入函数仍保留上次的值。
#include <stdio.h>
int runner(void) {
int count = 0;
count++;
return count;
}
int main(void) {
printf("%d ", runner());
printf("%d ", runner());
printf("%d\n", runner());
return 0;
}输出为 1 1 1:每次调用都会重新将 count 置为 0 再自增。
#include <stdio.h>
int runner(void) {
static int count = 0;
count++;
return count;
}
int main(void) {
printf("%d ", runner());
printf("%d ", runner());
printf("%d\n", runner());
return 0;
}输出为 1 2 3,适用于在函数内维护调用次数等跨次调用的状态。
static 与链接属性
| 对象种类 | 默认链接 | 加 static 后 |
|---|---|---|
| 局部变量 | 无(仅块作用域) | 仍为块作用域,但存储期延长为静态 |
| 全局变量 | 外部链接,其他翻译单元可用 extern 引用 | 内部链接,仅本文件可见 |
| 函数 | 外部链接 | 内部链接,仅本文件可调用 |
static 全局变量
在文件作用域定义的 static 全局变量不能被其他源文件通过 extern 访问,有助于避免符号冲突并隐藏实现细节。
static 函数
static void fun(void) {
printf("仅在本翻译单元内可见的辅助函数。\n");
}大型工程中,常将只在当前 .c 文件内使用的辅助函数声明为 static,避免与其他文件的同名函数冲突。
与全局变量的区别
static 全局对象与函数具有内部链接;未加 static 的文件作用域全局对象与函数默认具有外部链接,可在其他文件中声明后使用。若希望符号仅服务于当前模块,应使用 static。
练习:在不借助全局变量向形参传递累计值的前提下,用 static 局部变量实现 sum(n),连续调用 sum(55)、sum(45)、sum(50) 时,每次返回当前调用序列的累加和。