C语言:变量三属性——存储类型

C语言:变量三属性——存储类型

C语言变量具有三属性:类型,作用范围、存储类别

存储类别:

1、auto类别:

1.1、auto类别的变量使用完后释放所占用空间。

auto类别 = 临时变量

1.2、局部变量默认为auto类别无初始化时,初值为随机值。

局部变量(不是所有变量!!)不给初值并不意味着变量没有值,实际上是有的,而且是随机值。

1.3、使用时间短,一般都是auto类别的变量。

2、static类别:

2.1、static类别从定义到程序运行结束均占用存储空间。

占用时间比auto长。

2.2、全局变量默认为static类别,无初始化时,初值为0。

2.3、static类别变量只进行一次初始化。

案例1:

//09-6--001 #include <stdio.h> int fun(int x, int y) { static int m = 0,i = 2;//静态变量static i += m + 1; m = i + x + y; return m; } main() { int j = 4, m = 1, k; k = fun(j, m); printf("%d", k); k = fun(j, m); printf("%d", k); }

该案例是一个复合框架,由一个子函数fun()和一个主函数main()组成。

主函数调用子函数两次。

从主函数main开始执行,定义了3个局部变量j=4,m=1,k为随机值。

接着开始调用子函数,函数出门,出门时单向传值,将j=4与m=1传至子函数。

因此x=4,y=1,继续执行子函数fun(),定义了两个静态变量,分别是m=0,i=2,静态变量只做一次初始化,所以原代码中我们定义好m和i后,那一句带static的话就没有用了。

继续往下,i+=m+1,是先算m+1,放到i里,再进行累加。那么i此时i=2+1,i=3。继续往下,m=i+x+y,其中i=3,x=4,y=1,所以m=8。继续往下,return m,带着m的值返回,所哟就带着8返回了。

回到主函数原本调用的位置继续运行,k=fun(j,m),8这个值给了fun(),所以fun()=8,所以k=8,继续运行,打印k的值,输出打印8,光标在8后。

继续运行,再次调用子函数,函数出门,出门时单向传值,再次将j=4与m=1传至子函数。再次运行一遍子函数,但是前面已经用过一次static语句了,第二次再用,就会跳过static语句,注意注意,此时m的值就不是static初始化的0了,i的值也不是初始化的2了,而是沿用上一次留下来的数据,m=8,i=3继续使用。

继续往下运行,i+=m+1,是先算m+1,放到i里,再进行累加。m+1=8,8+1=9,此时就把9累加进i里,i=9+3=12,i变成12.继续往下运行m=i+x+y,i=12,x=4,y=1,所以此时m=17。继续往下,return m,那么就带着17回主函数了。

回到主函数,k=fun(),带回来的值是17,17这个值给了fun(),所以fun()=17,所以k=17,继续运行,打印k的值,输出打印17,光标在17后。

分析结束,所以最后的输出框输出的应该是817。我们上机看一下最终的效果:

重点体会static变量第一次调用和第二次调用之间的区别。认真体会“static类别变量只进行一次初始化”在代码中的具体体现。

案例2:

//09-6--002 #include <stdio.h> int d = 1; fun(int p) { static int d = 5;//静态变量static d += p; printf("%d", d); return (d); } main() { int a = 3; printf("%d\n", fun(a+fun(d))); }

代码开头有一个d,是全局变量。但是在子函数内也有一个d,是static变量,只做一次初始化。

在主函数内也出现了一个d,那么这个d就应该是全局变量d,因为子函数内的d的作用范围只在子函数内。因此主函数内的fun(d),其中的d=1。

开始分析。这是个包括一个子函数和一个主函数的复合框架。子函数在上无需声明。在主函数内调用子函数两次。最后printf。

fun()子函数前没有规定类型,那fun()返回什么类型?应该是默认返回Int类型,int类型即非void类型,一定要加return。

从主函数进入,开始执行,首先定义了一个a=3,接下来在printf语句内开始两次调用fun()函数,先调用内层的函数fun(d),我们已知d=1,调用完内层的函数,会返回一个值,来与前面的a相加继续计算,再进行一次调用。

好,那么开始调用fun(d),函数出门,前往fun()单向传值,那么p=1。继续往下,static int d=5,单次初始化,那么d此时被初始化为5,d=5,初始化结束后static语句失效。继续往下,d+=p,将p的值累加进d后再赋值给d,所以此时d的值被更新为6,printf语句输出d的值,即输出一个6。继续往下return语句,带着d的值d=6,返回原先调用的地方。

回到主函数,fun(d),带回来的值是6,6这个值给了fun(),所以fun(d)=6,带入前面的式子,那么变成了fun(a+6)。又因为原a=3,所以fun(9),将会再调用一次fun,这次带入的值是9。

好,那么开始调用fun(9),函数出门,前往fun()单向传值,那么p=9。继续往下,static语句已经失效了,忽略不看,直接运行d+=p,此时将p的值累加进d后再赋值给d,p=9,d=6,d的值沿用上一次调用留下来的值,所以此时d的值被更新为15。继续往下打印d的值,所以打印15。继续往下,带着15这个值回到原先调用的主函数的地方。

回到主函数,那么此时fun(a+6)的值已被更新为15。printf语句打印15,且换行。

分析结束,所以最终应该输出61515回车,光标在下一行开头。我们上机看一下最终的效果:

重点体会static变量第一次调用和第二次调用之间的区别。认真体会“static类别变量只进行一次初始化”在代码中的具体体现。

3、register类别(寄存器类别):

3.1、register类别变量只能是局部变量才能被说明。

3.2、register类别变量一般不能直接使用

4、extern类别:

4.1、extern类别变量可以加大变量的作用范围(外部)

案例3:

//09-6--003 #include <stdio.h> main() { printf("%d,%d\n", x, y); } int x, y;

可以看到,本案例希望可以实现输出x和y,但是代码实际上是先使用,再定义,原本c语言中应该先定义后使用,所以在编译是就会提醒未声明。

但是我们代码末尾有定义呀,那么我们就可以通过extern来加大x和y的作用范围。

增加语句:extern x,y;

增加句子之后程序正常运行。

4.2、格式说明:

格式1(auto、static、register只能使用格式1):定义的同时说明类别:

存储类型 类型名 变量名;

eg:auto int x;-----auto可省略

static int x;-----YES

格式2(extern可以用格式1也可以用格式2):分别定义,说明:

类型名 变量名;

存储类型 变量名;

eg:extern int x;或者 int x;extern x;

学习过程有诸多不足之处,欢迎来私信与我一同交流学习,共同进步!