1. 作用域
1.1. 变量之分
1.1.1. 局部变量
大括号{}以内的变量,都是局部变量,形参也是局部变量,作用域起始于定义处,截止于所在的大括号,若未赋值,值是随机的
1.1.2. 全局变量
大括号{}以外的变量,都是全局变量,作用域起始于定义处,截止于本文件结束,若未赋值,系统将其初始化为0
1.2. 作用域
1.2.1. 定义
void foo(int a)
{
a++;
printf("a = %d\n", a); // a = 6
// int a; // 不同作用域内可以重名,同一作用域内则会发生重定义
}
int main()
{
int a = 5;
foo(a);
printf("a = %d\n", a); // a = 5
return 0;
}
1.2.3. 作用域叠加
当小范围内的作用域和大范围的作用域,出现叠加,且有重名变量的时候,小范围作用域内的变量名会覆盖大范围作用域内的变量名。
1.2.4. 全局命名污染
在全局作用域内,如果有重名则会造成重定义。要尽量少用全局变量。
2. 生命周期
2.1. 局部变量
局部变量的生命周期,同其所在的函数,局部变量随着函数的执行而有生命,随着函数的执行结束而生命截止。
进程随着main函数的执行而开始,随着main函数的结束而结束,main函数中的局部变量的生命周期同main函数或同进程。
2.2. 全局变量
全局变量的生命周期同进程
3. 修饰符
修饰符在变量定义的类型之前,或改变生命周期,或改变存储区域,或均有所改变。
auto int a
3.1. extern
extern只能用来修饰全局变量,全局变量本身是全局可用的,对于不是在本范围内定义的全局变量,要想使用,必须用extern声明,如果不加extern,会造成重定义
注意:经extern声明的变量,不可以再初始化
3.1.1. 同文件
extern int a;
int main(void)
{
printf("a = %d\n", a);
return 0;
}
void func()
{
printf("Hello world\n");
}
int a = 5;
3.1.2. 跨文件
C语言是单文件编译的,然后再将编译的.o文件同库一起链接成可执行文件,所以,跨文件使用全局变量,需要声明
如果main.c中没有extra int a,由于后面又使用了变量a,则会报错。
3.2. static
3.2.1. 修饰局部变量
static修饰局部变量,修改了局部变量的生命周期,使其生命周期同进程或main函数。
static变量若未初始化,则系统初始化为0,并且只进行一次初始化。
void func()
{
int i = 5;
printf("i = %d\n", i);
static int count = 0; // 初始化赋值的不同
count++;
printf("count = %d\n", count);
}
int main()
{
func(); // count = 1
printf("++++++++++++++++\n");
func(); // count = 2
printf("+++++++ +++++++++\n");
func(); // count = 3
printf("++++++++++++++++\n");
return 0;
}
3.2.2. 静态局部变量应用
用于流程控制
void print(int num, int age, char sex, int grade)
{
static int flag = 1;
if (flag == 1)
{
printf("学号\t 年龄\t 性别\t 年级\n");
flag = 0;
}
static int count = 0;
printf("%d\t %d\t %c\t %d -> %d\n", num, age, sex, grade, count);
}
int main()
{
print(1001, 11, 'm', 2);
print(1002, 12, 'f', 3);
print(1003, 10, 'm', 4);
}
3.2.3. 修饰全局变量
static修饰全局变量,使其成为仅在本文件内部使用的全局变量。
全局变量会带来全局命名空间的命名污染,这样保留了全局变量的使用便利性,又不会造成全局空间的命名污染