导言:
在C语言中,变量的存放位置有多种,可以存放在栈区,可以存放在全局静态区等(这些区域都是对内存划分的结果),一般对于变量而言,我们比较关注它的生命周期和作用域:
生命周期:从变量的空间被申请,直至空间被释放掉的这段时间(所在的{}内,{}结束,该变量被自动释放)
作用域:所在{}内,出了{},变量就没用了
一、自动变量(局部变量/栈区变量)
如 int a ,int a[4],int *p ,struct AAA a[3]这些都是局部变量(函数的形参也是局部变量,如void fun(int a,int b){}针对于fun这个函数,a和b变量也是局部变量,只在所在的{}范围内起作用),局部变量又称为自动变量或者栈区变量,它只在它本身所在的{}范围内起作用(从声明变量的位置开始),一出这个范围,就失效了(生命周期结束),请看如下代码:
#include <stdio.h>
int main(void)
{
int a;
{
int b;
b = 23;
a = 32;
}
return 0;
}
分析1:变量a的范围是在最外层的{}内,在最外层的{}内,均可以使用变量a,而b的作用范围是在内层的{},如果出了内层的{},那么b就不再生效了。以上的代码是没有问题的,与我们所讲的理论相符合。再来看如下代码:
#include <stdio.h>
int main(void)
{
int a;
{
int b;
b = 23;
a = 32;
}
b = 55;
return 0;
}
如果是用以上的代码,进行编译的话,那么会出现如下错误:
分析2:因为b的作用范围是在内层的{}内,如果出了这个范围,那么b就已经消失了,不能够再次使用它了,因此编译器报了这样一个错误。
注意:
#include <stdio.h>
int main(void)
{
auto int a;
int b;
return 0;
}
分析:我们在编码中定义变量常常使用int a的形式,其实也可以这样auto int a,这两者是完全等价的。
二、静态变量(此处的静态变量包含全局变量)
特点:
存储位置:静态区/静态全局区/静态存储区
特性:①静态变量会被自动初始化成0 ②生命周期与程序共存亡 ③在程序运行时(第一步就是要加载资源),在加载资源阶段分配空间(在执行主函数之前,需要加载程序所需资源,对于局部变量空间的开辟是在程序运行的阶段)
1.全局变量/外部变量(外部可以使用,当前文件可以使用,其它文件也可以使用)
特点:在{}范围外,在不手动进行初始化的情况下,编译器默认为全局变量进行了初始化,如果是int型变量初始化为0,如果是指针,初始化为NULL
注意:全局变量的定义 int a =12 ;与 此条语句等价:extern int a = 12;因为本身全局变量就是外部变量,一般而言extern 加在声明处,用来说明int a已经定义(让看代码的人更明确),一般这是属于一种共识.
#include <stdio.h>
int a ;
int b[3];
int *p ;
struct Node
{
int a;
double b;
}node ;
int main(void)
{
printf("%d\n",a);
printf("%d,%d,%d\n", b[0],b[1],b[2]);
printf("%p\n", p);
printf("%d,%lf\n", node.a,node.b);
return 0;
}
观察如下运行结果:
注意:① 在全局变量的位置,只能写函数的声明,变量的声明或者初始化,并且变量的初始化只能使用常量进行初始化
② 所有文件均可见,但是必须先声明,声明后才能使用,比如int a =12 ;已经在主文件中定义,那么在别的文件如果想要使用a这个变量的话,必须先使用int a;语句进行声明,记住,此时仅仅是声明。
2.静态全局变量
含义:将全局变量加上一个存储类说明符static。
生命周期:和程序共存亡。
作用域:只在所在的文件内有效
3.静态局部变量
含义:将局部变量加上一个存储类说明符static。
作用域:只在所在的{}内有效(与局部变量作用域一样)
生命周期:与程序共存亡
例子:
#include <stdio.h>
void fun()
{
int a = 1;
static int b = 1;
a++;
b++;
printf("a:%d,b:%d\n",a,b);
}
int main(void)
{
fun();
fun();
fun();
return 0;
}
结果截图: