全局变量
认识全局变量
定义在函数外的变量就是全局变量全局变量具有全局的生存期和作用域它们与任何函数无关任何函数(定义在全局变量后的的函数)内部都可以使用它们
例如:
intf(void);intgAll=12;intmain(void){//__func__可以打印出当前函数的函数名,下划线一边是两个printf(in%sgAll=%d\n,__func__,gAll);//全局变量可以直接使用,不需要再声明f();printf(againin%sgAll=%d\n,__func__,gAll);//函数内对全局变量值的改变在main函数中依然存在return0;}intf(void){printf(in%sgAll=%d\n,__func__,gAll);gAll+=2;printf(againin%sgAll=%d\n,__func__,gAll);returngAll;}
输出:
inmaingAll=12infgAll=12againinfgAll=14againinmaingAll=14
全局变量的初始化
没有初始化的全局变量默认值为0指针默认为NULL只能用编译时刻已知[1]的值来初始化全局变量全局变量的初始化发生在main函数之前注释1:
intgAll=12;intg=gAll;//报错intmain(void){return0;}
下面这段代码在某些编译器(devc++)上是可以编译的,但是在vs上是不能编译的
constintgAll=12;intg=gAll;intmain(void){return0;}
但是,这种方式是不推荐的
被隐藏的全局变量
如果函数内部存在与全局变量同名的变量,则全局变量被隐藏。
intf(void);intgAll=12;intmain(void){printf(in%sgAll=%d\n,__func__,gAll);f();printf(againin%sgAll=%d\n,__func__,gAll);return0;}intf(void){intgAll=2;//仅在这个范围内适用printf(in%sgAll=%d\n,__func__,gAll);gAll+=2;printf(againin%sgAll=%d\n,__func__,gAll);returngAll;}
输出:
inmaingAll=12infgAll=2againinfgAll=4againinmaingAll=12
即使gAll在main函数中被覆盖,f函数中的gAll也是不会被该改变的
为什么会这样?自己思考一下。
静态本地变量
在本地变量定义时加上static修饰符就成为静态本地变量当离开函数的生存期后,静态本地变量会继续存在并保持其值静态本地变量的初始化只会在第一次进入这个函数时进行,以后进入函数时会保持上次离开时的值。例:不用static的情况
intf(void);intmain(void){f();f();f();return0;}intf(void){intAll=1;printf(in%sAll=%d\n,__func__,All);All+=2;printf(againin%sAll=%d\n,__func__,All);returnAll;}
输出:
infAll=1againinfAll=3infAll=1againinfAll=3infAll=1againinfAll=3
使用static:
intf(void);intmain(void){f();f();f();return0;}intf(void){staticintAll=1;//只添加staticprintf(in%sAll=%d\n,__func__,All);All+=2;printf(againin%sAll=%d\n,__func__,All);returnAll;}
输出:
infAll=1againinfAll=3infAll=3againinfAll=5infAll=5againinfAll=7
看看地址
intf(void);intgAll=12;intmain(void){printf(1st\n);f();printf(2nd\n);f();return0;}intf(void){inta=0;intb=0;staticintAll=1;printf(All:%p\n,All);printf(gAll:%p\n,gAll);printf(a:%p\n,a);printf(b:%p\n,b);returnAll;}
输出:
1stAll:FF6A9ECCgAll:FF6A9ECCa:ECF8B4b:ECF8D42ndAll:FF6A9ECCgAll:FF6A9ECCa:ECF8B4b:ECF8D4
全局变量gAll与静态局部变量All在内存中相邻
总结
静态本地变量实际上是特殊的全局变量它们位于相同的内存区域静态本地变量具有全局的生存期,函数内的局部作用域返回指针的函数
请同学们先看一下下面这个程序:
int*f(void);voidg(void);intmain(void){int*p=f();printf(*p=%d\n,*p);g();printf(*p=%d\n,*p);return0;}int*f(void){inti=12;returni;}voidg(void){intk=24;printf(k=%d\n,k);returnk;}
输出:
*p=12k=24*p=24
i和k的内存其实是同一块空间
总结
返回本地变量的地址是危险的返回全局变量或静态局部变量的地址是安全的返回函数内malloc的内存是安全的,但是容易造成问题最好的做法是返回传入的指针说了这么多,总结一句话
尽量避免使用全局变量和静态本地变量
为什么这里就不深讲了,有兴趣的朋友可以下来自己查查。
编译预处理与宏
编译预处理指令
#开头的是编译预处理指令它们不是C语言的一部分,但是C语言离不开他们#define用来定义一个宏define关键字
回想我们刚学double的时候,是不是计算过圆的面积。当时我们可能是这样写的:
#includestdio.hconstdoublePI=3.;intmain(void){printf(%f\n,2*PI*3.0);return0;}
现在我们用宏就不需要用const修饰的全局变量了,我们也说过,全局变量最好不用。
#includestdio.h#definePI3.//注意:不写分号不写等于号intmain(void){printf(%f\n,2*PI*3.0);return0;}
现在,我们打开我们的虚拟机,进入Linux系统。
现在多出来了4个文件,蓝色的是文件夹,我们不去管它,绿色的是可执行文件,类似windows的.exe文件现在我们主要