作用域(Scope)决定了标识符在程序的哪些部分可见,生命周期(Lifetime)决定了变量在何时分配和释放内存。
| 作用域类型 | 说明 | 示例 |
|---|---|---|
| 块作用域 | 仅在{}内可见 |
for循环内的变量 |
| 函数作用域 | 整个函数内可见 | goto标签 |
| 文件作用域 | 从定义到文件末尾可见 | 全局变量、static函数 |
| 函数原型作用域 | 参数列表中可见 | 声明中的参数名 |
| 存储类 | 生命周期 | 存储位置 |
|---|---|---|
| 自动变量(auto) | 函数调用期间 | 栈 |
| 静态局部变量(static local) | 程序运行期间 | 静态存储区 |
| 全局变量 | 程序运行期间 | 静态存储区 |
| 动态分配变量 | 直到free()释放 |
堆 |
// 自动变量(默认)
int auto_var = 10; // 等同于 auto int auto_var = 10;
// 静态局部变量
void func(void) {
static int count = 0; // 只初始化一次,值保留到程序结束
count++;
}
// 全局变量
int global_var = 100;
// extern声明(引用其他文件的全局变量)
extern int global_var;
// static全局变量(限制在本文件可见)
static int file_local_var = 200;
#include <stdio.h>
// 全局变量
int global_counter = 0;
// static全局变量,仅本文件可见
static int file_counter = 0;
void demonstrate_scope(void) {
// 局部变量
int local_var = 10;
// 静态局部变量
static int static_var = 0;
printf("local_var = %d, static_var = %d\n", local_var, static_var);
local_var += 5;
static_var += 10;
global_counter++;
file_counter++;
}
void demonstrate_block_scope(void) {
int x = 100; // 函数作用域
{
int x = 200; // 块作用域,隐藏外层x
printf("Inner x = %d\n", x);
}
printf("Outer x = %d\n", x); // 恢复外层x
}
int main() {
printf("=== 调用前 ===\n");
printf("global_counter = %d, file_counter = %d\n",
global_counter, file_counter);
for (int i = 0; i < 5; i++) {
demonstrate_scope();
}
printf("\n=== 调用后 ===\n");
printf("global_counter = %d, file_counter = %d\n",
global_counter, file_counter);
demonstrate_block_scope();
// extern示例(引用其他文件的变量)
// extern int external_var; // 需要在其他文件定义
return 0;
}
编译命令:
gcc -Wall -Wextra -o scope_lifetime scope_lifetime.c
./scope_lifetime
Q1: static局部变量和全局变量有什么区别? A: 生命周期相同(程序全程),但作用域不同。static局部变量只在块内可见,全局变量在声明后整个文件可见(配合extern可跨文件)。
Q2: 为什么说全局变量不是好习惯? A: 全局变量增加模块耦合,难以追踪修改,多线程环境需要同步,不利于代码复用和测试。
Q3: auto关键字在C语言中有什么作用?
A: auto是默认存储类,表示自动存储(栈上)。在C语言中几乎不写,因为默认就是auto。
Q4: 如何在函数间共享数据但不使用全局变量? A: 使用static全局变量(文件作用域)、通过函数参数传递指针、使用结构体封装数据。
Q5: 文件作用域和函数作用域有什么区别? A: 文件作用域从定义处到文件末尾可见,函数作用域仅在函数内可见(如goto标签)。两者生命周期都是程序全程。