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) 时,每次返回当前调用序列的累加和。