C/C++ 中 `static` 关键字

C/C++ 中 static 关键字详解

static 是 C/C++ 中一个非常重要的关键字,用途灵活。它既可以修饰全局变量,也可以修饰局部变量和函数。在 C++ 中还可以修饰类成员变量和成员函数。本文将从不同角度详细讲解 static 的作用、生命周期和使用场景。


1. static 修饰全局变量

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>

static int counter = 0; // 仅当前文件可见

void add() {
counter++;
printf("counter = %d\n", counter);
}

int main() {
add(); // counter = 1
add(); // counter = 2
add(); // counter = 3
return 0;
}

特点

  • 生命周期:和普通全局变量一样,从程序开始到程序结束。
  • 作用域:仅在当前源文件可见,无法通过 extern 在其他文件访问。
  • 多次访问:变量值会一直保留,不会因为函数调用结束而销毁。

对比普通全局变量

特性 普通全局变量 static 全局变量
生命周期 整个程序运行期间 整个程序运行期间
作用域 跨文件可见 当前文件可见
初始化次数 程序启动时一次 程序启动时一次
多次访问效果 同一份存储空间,值累积 同一份存储空间,值累积

使用 static 修饰全局变量可以避免命名冲突,增强封装性。


2. static 修饰局部变量

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <stdio.h>

void demo() {
static int count = 0; // 局部静态变量
count++;
printf("count = %d\n", count);
}

int main() {
demo(); // count = 1
demo(); // count = 2
demo(); // count = 3
return 0;
}

特点

  • 生命周期:从程序开始到程序结束,与全局变量一样。
  • 作用域:仅在定义的函数内部可见。
  • 多次访问:每次调用函数时,变量不会重新初始化,保留上一次的值。

3. static 修饰函数

示例

1
2
3
4
5
6
7
8
9
10
#include <stdio.h>

static void hello() {
printf("Hello, static function!\n");
}

int main() {
hello();
return 0;
}

特点

  • 作用域:仅在定义的源文件内部可见,无法在其他文件中调用。
  • 用途:限制函数的访问范围,防止命名冲突。

4. C++ 中 static 的使用

4.1 类静态成员变量

  • 作用:类共享的变量,不属于某个对象实例。
  • 访问方式:通过类名或对象实例访问。
  • 存储期:静态存储期。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream>
using namespace std;

class MyClass {
public:
static int count; // 声明
MyClass() { count++; }
};

int MyClass::count = 0; // 定义并初始化

int main() {
MyClass a;
MyClass b;
cout << "Count: " << MyClass::count << endl; // Count: 2
return 0;
}

4.2 类静态成员函数

  • 作用:静态函数只能访问静态成员变量,不能访问非静态成员。
  • 调用方式:通过类名或对象调用。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class MyClass {
public:
static void printCount() {
cout << "Count: " << count << endl;
}
static int count;
};

int MyClass::count = 0;

int main() {
MyClass::count = 10;
MyClass::printCount(); // 输出 10
return 0;
}

4.3 匿名命名空间替代 static(C++ 特有)

在 C++ 中,static 修饰全局函数和变量可以被匿名命名空间替代:

1
2
3
4
namespace {
int counter = 0; // 等效 static int counter;
void helper() {} // 等效 static void helper();
}

匿名命名空间是 C++ 推荐的做法,比 static 更语义化。


5. 总结

使用场景 生命周期 作用域 特点
全局变量 static 程序运行期 文件内部 限制文件可见性
局部变量 static 程序运行期 函数内部 保留函数调用间的值
函数 static 程序运行期 文件内部 文件内可见,不被其他文件引用
类静态成员变量 程序运行期 类作用域 所有对象共享
类静态成员函数 程序运行期 类作用域 仅能访问静态成员