static是C语言中的一个重要关键字,它有多种用法,主要分为三种情况:

static修饰局部变量

特性:
延长生命周期:使局部变量的生命周期变为整个程序运行期间
保持持久性:变量只初始化一次,函数调用结束后值不会销毁
作用域不变:仍然只能在定义它的函数内部访问

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <stdio.h>
void test()
{
static int count = 0; // 只初始化一次
count++;
printf("Count: %d\n", count);
}
int main()
{
test(); // 输出: Count: 1
test(); // 输出: Count: 2
test(); // 输出: Count: 3
return 0;
}

内存分配:

  • 普通局部变量:存储在栈区,函数结束时释放
  • static局部变量:存储在静态存储区(数据段),程序结束时释放

static修饰全局变量

特性:
限制作用域:将全局变量的作用域限制在当前源文件内
防止外部链接:其他源文件无法通过extern声明访问
避免命名冲突:在不同文件中可以有同名的static全局变量

1
2
3
4
5
// file1.c
static int hidden_global = 10; // 只在file1.c中可见

// file2.c
extern int hidden_global; // 错误!无法访问file1.c中的static全局变量

static修饰函数

特性:
限制作用域:将函数的作用域限制在当前源文件内
内部链接:只能在定义它的文件中调用
实现封装:隐藏函数实现,提供模块化设计

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// math_utils.c
static int helper_function()
{ // 内部辅助函数
return 42;
}

int public_function()
{ // 可被外部调用的函数
return helper_function();
}

// main.c
int helper_function(); // 错误!无法声明static函数
int public_function(); // 正确!可以声明和调用

应用场景

计数器

1
2
3
4
5
int get_unique_id()
{
static int id = 0;
return ++id;
}

单例模式(简化版)

1
2
3
4
5
struct Config* get_config() 
{
static struct Config config;
return &config;
}

缓存上次计算结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
int fibonacci(int n) 
{
static int cache[100] = {0};

if (n <= 1) return n;

if (cache[n] == 0)
{
cache[n] = fibonacci(n-1) + fibonacci(n-2);
}
return cache[n];
}
#include <stdio.h>
int main()
{
printf("F(10) = %d\n", fibonacci(10)); // 第一次:计算并缓存
printf("F(10) = %d\n", fibonacci(10)); // 第二次:直接从缓存读取
printf("F(5) = %d\n", fibonacci(5)); // 直接从缓存读取
printf("F(15) = %d\n", fibonacci(15)); // 只计算新的部分

return 0;
}

初始化规则

static变量的初始化:

  • 自动初始化为0(数值类型)或NULL(指针类型)
  • 只在第一次进入作用域时初始化
1
2
3
4
5
void example() {
static int a; // a初始化为0
static int b = 10; // b初始化为10(只初始化一次)
static int* ptr; // ptr初始化为NULL
}