void f() {
    static int cnt = 0;
    cnt++;
    cout << cnt << " ";
}
int main() {
    f(); f(); f();
    return 0;
}

输出:1 2 3

static局部变量核心考点

  1. static int cnt = 0;只在第一次调用函数的时候初始化一次,后续调用不再执行cnt=0
  2. 变量不存栈上,存静态存储区;函数结束,cnt的值不会销毁,保留上次的值

执行流程:

  1. 第1次f():cnt初始化为0 → cnt++ → cnt=1,输出1
  2. 第2次f()不再执行static初始化,沿用旧值1 → cnt++ → cnt=2,输出2
  3. 第3次f():cnt=2 → cnt++ → cnt=3,输出3

对比普通局部变量(去掉static)

void f(){
    int cnt=0;
    cnt++;
    cout<<cnt<<" ";
}

每次进入函数都重新赋值cnt=0,输出:1 1 1

CSP高频坑

  • static局部变量初始化仅一次,不是每次函数调用都初始化。
  • 生命周期:整个程序运行期间;作用域依旧只在函数内部,外面不能直接访问cnt。

变式练习:

void g(){
    static int a=10;
    a+=2;
    cout<<a<<" ";
}
int main(){
    g();g();
}

输出?👉12 14

扩展:static局部变量 vs 全局变量

生命周期一样,但作用域不一样,不完全等效!

//全局变量
int cnt = 0;
void f(){
    cnt++;
    cout<<cnt;
}
void f(){
    static int cnt=0;
    cnt++;
    cout<<cnt;
}

✔相同点

  1. 都放在静态存储区,不是栈;程序启动分配内存,程序结束才释放。
  2. 初始化只做一次
  3. 函数调用结束,变量值保留,不会被销毁。

❗关键区别(CSP必考点)

1. 作用域(可见范围)

  • static局部变量仅函数内部可以访问,函数外面main不能直接写cnt;外面看不见。
void f(){
    static int cnt=0;
}
int main(){
    cnt = 100; //编译报错!main看不见f里面的static cnt
}
  • 全局变量:整个文件所有函数都可以直接访问。
int cnt=0;
void f(){}
int main(){
    cnt=100; //合法,随便改
}

2. 初始化时机

  • 全局变量:main执行之前就完成初始化。
  • static局部变量:第一次调用这个函数的时候,才初始化
void f(){
    static int x=100; //第一次跑到f()才执行x=100
}

如果程序从头到尾没有调用f(),这个x永远不会初始化。

全局变量,不管函数跑不跑,main之前就初始化完毕。

3. 名字冲突

static局部变量名字只在函数内有效,别的函数可以再定义同名static变量,互不干扰。 全局变量整个文件不能重名。

一句话总结

生命周期等价,但是作用域不等价。static局部变量相当于“藏在函数里面的全局变量”,外面访问不到。

做题小坑

阅读程序看到static int x=0;写在函数里面:

  • 值会跨调用保留;
  • 但是别的函数不能直接用这个x

变式

void A(){
    static int t=1; t++; cout<<t;
}
void B(){
    static int t=100;t++;cout<<t;
}
int main(){
    A();A();B();
}

输出:2 3 101,两个t互不干扰。