- 定义在函数外的变量是全局变量;
- 具有全局的生存期和作用域;
- 与任何函数无关;
- 在任何函数内部都能访问和使用。
- 程序内所有位置都能访问和修改全局变量,且块内修改结束后,全局变量的修改仍然有效。(本地变量只在块内有效)
#includeint f(void); int gAll = 12; //全局变量 int main(){ printf("在%s函数内,gAll = %dn", __func__, gAll); //__func__是输出所在函数的函数名 f(); printf("调用f之后,在%s函数内,gAll = %dn", __func__, gAll); return 0; } int f(void) { printf("在%s函数内,gAll = %dn", __func__, gAll); gAll += 2; printf("在%s函数内加2后,gAll = %dn", __func__, gAll); return 0; }
输出结果:
int gAll = 12; //合法初始化 int gAll = f(); //非法初始化 int gAll = 12; int g2 = gAll; //非法初始化 const int gAll = 12; int g2 = gAll; //合法初始化, 但不建议如此操作 int g2 = gAll; //非法初始化 const int gAll = 12;
3、隐藏全局变量说明:
- 全局变量未初始化时默认为0(本地变量不一定默认为0,是未知的值);
- 未初始化的指针型全局变量为NULL;
- 全局变量的初始化器只能是编译时的已知值(常量)。
- 全局变量的初始化的值不建议和另一个全局变量相联系;
- 全局变量的初始化发生在 main 函数之前。
若函数(代码块)内部存在与全局变量同名的变量,则全局变量比隐藏
#includeint f(void); int gAll = 12; //全局变量 int main(){ printf("在%s函数内,gAll = %dn", __func__, gAll); //__func__是输出所在函数的函数名 f(); printf("调用f之后,在%s函数内,gAll = %dn", __func__, gAll); return 0; } int f(void) { int gAll = 2; //与全局变量同名的本地变量 printf("在%s函数内,gAll = %dn", __func__, gAll); gAll += 2; printf("在%s函数内加2后,gAll = %dn", __func__, gAll); return 0; }
输出结果:
- 在程序块内,存在和全局变量同名的本地变量时,该同名变量被视为本地变量,且具有本地变量的性质(生存期和块作用域)。
二、静态本地变量 —— static
静态本地变量 —— 在函数结束之后,仍然能保留其原有的值,不会因所在块的结束而失效。
性质:
- 快作用域。只在所在程序块有效;
- 静态存储期。离开函数之后,其值仍被保留;
- 静态本地变量的初始化只会在其首次进入所在函数时进行,此后进入该函数都会保留上次离开时的值。
举例:
#includeint f(void); int main(){ f(); f(); f(); return 0; } int f(void) { static int a = 1; //静态本地变量 printf("在%s函数内,a = %dn", __func__, a); a += 2; printf("在%s函数内加2后,a = %dn", __func__, a); return 0; }
输出结果:
静态本地变量在定义之后就具有静态存储期,不会因为所在代码块结束而失去原有的值,反而其值在所在代码块结束之后仍被保留,在下一次调用该函数时,静态本地变量不会被重置。
三、本地变量、静态本地变量、全局变量 的比较
- 静态本地变量实际上是一种特殊的全局变量,二者均存储在相同的内存区域 —— 静态存储区。
- 静态本地变量具有全局的生存期,具有函数内的局部作用域。
| 变量类型 | 生存期 | 作用域 |
|---|---|---|
| 本地变量 | 自动存储期 (在函数中声明后生效,函数返回后失效) | 块作用域 (在函数中声明至所在函数体的结尾) |
| 静态本地变量 | 静态存储期 (在函数中声明后生效,函数返回后依然保留其值) | 块作用域 (在函数中声明至所在函数体的结尾) |
| 全局变量 | 静态存储期 (变量声明后始终有效) | 全局作用域 (被声明的位置至所在文件的结尾均有效) |
四、返回指针的函数 4.1 警告
- 函数不能返回其内部的本地变量的地址,结果不可控;
- 返回全局变量或静态本地变量的地址是安全的;
- 返回在函数内 malloc 的内存是安全的,但容易造成问题;
- 最好是返回传入的指针。
- 不要使用全局变量在函数间传递参数或结果;
- 尽量避免使用全局变量;
- 使用全局变量和静态本地变量的函数对于多线程是不安全的。



