由于容易忘记static关键字的用法,每次搜索还得筛选一下才能得到想要的结果。故写下此文章记录。

一、C

C语言中,static可以用来修饰全局变量局部变量函数

1.1 Cstatic修饰的全局变量

C语言中,当一个全局变量被static修饰后,其特征:

  • 在全局数据区分配内存(这点没变化)
  • 仅在声明的时候初始化,如果未初始化,默认赋值为0
  • 作用域为本文件内,从定义开始到文件末尾(可见性)

1.2 Cstatic修饰的局部变量

  • 全局数据区分配内存(原本在栈区)
  • 仅能被初始化一次
  • 作用域为本函数中,从定义处到该函数的末尾

来做几个小实验。
例1. 验证局部变量初始化行为

/*
 * main.c
 */
#include <stdio.h>

static int g_int_uninit;
static int g_int = 1023;

void foo(int num) {
    static int l_int_uninit;
    printf("static local uninit var = %d\n", l_int_uninit);
    static int l_int = 1;    // 调用了五次,实际上只生效了一次(**第一次被调用时**)
    l_int += num;
    printf("after foo(), static local var = %d\n", l_int);
}

int main() {
    printf("global static uninit int = %d\n", g_int_uninit);
    printf("global static int = %d\n", g_int);
    for (int i = 0; i < 5; ++i)
        foo(5);
    return 0;
}

在例1的基础上,稍作小改动,声明引入了一个定义在其他文件的变量(定义在test.h中,是一个全局静态变量)。编译没问题,但是链接提示找不到符号。证明作用域确实被修改了。
图1. 引用外部static变量报错

1.3 Cstatic修饰的函数

  • 修改“可见性”,仅在当前文件生效。
    这点和修饰变量时相似,注意这里的“可见性”用引号圈起来了。
    C语言里面,定义在一个文件里的函数,默认是全局可见的。而static关键字能够改变这一性质,使其仅能在当前文件中可见(可被调用)。(这个有待求证,用GCC 8.3.0实际测试是可以访问的)

    二、C++

    C++中,static关键字的作用与C中大同小异。
    相较于CC++多了对象的概念,因此会有些更多用法。

    2.1 C++static修饰成员函数

  • 该成员函数不与类实体绑定,即能在不实例化类对象的情况下被调用。

    三、用途

3.1 单例模式的实现

C++单例设计模式的实现方法之一,借助了静态局部变量初始化以后不会再初始化的特点。(线程安全在C++11(含)标准以后支持)

class Singleton {
public:
    static Singleton* GetInstance() {
        static Singleton* s = new Singleton();    // C++11以后是线程安全的
        return s;
    }
private:
    Singleton();
    ~Singleton();
};

3.2 改变生命周期/仅初始化一次

略。

四、总结

五、参考资料

  1. https://en.wikipedia.org/wiki/Static_(keyword)
  2. https://en.wikibooks.org/wiki/C_Programming/Variables#static
  3. https://stackoverflow.com/questions/572547/what-does-static-mean-in-c