写在开头
对于很多C/C++的初学者来说,很容易理不清变量的作用域和存储类型这一块的一些概念,也容易将其中的一些概念搞混淆。作为一个C/C++的初学者,笔者希望在这里能够尝试着去理一理这些较为繁杂的概念,主要当作自己备忘之用。当然,由于笔者水平有限,经验不足,在这里也只能罗列一些常用概念和使用方法,且可能会有些许不专业之处,望君理解并指正。
一定要把变量的作用域和存储类型分开来看
很多人很容易把变量的作用于和存储类型搞混,但其实只要我们从它们定义出发来看,这个问题是很容易解决的。作用域是一个变量能够被使用的范围,而存储类型则是变量的存储方式,且存储类型决定着变量的生存期。
通俗地讲,存储类型决定着一个变量在某位置存不存在,而作用域决定着一个变量在某位置能不能被使用。比如:
1 /*例1*/ 2 #include<stdio.h> 3 int main() 4 { 5 static int a=1;//定义了一个静态存储的局部变量 6 return 0; 7 }
a是一个采用静态存储的局部变量,像这样的变量在整个文件中都不会消失,但是只能在main()函数内被使用。
作用域类型
在C语言中有块作用域、函数作用域、函数原型作用域,以及文件作用域,在C++中还有类作用域和命名空间作用域。由于在各类资料中关于这几类作用域的介绍已经相当丰富,在此我就不展开介绍了。在这几类作用域中,除了函数作用域均可根据名称来理解,如“具有块作用域”就是说明该变量在对应代码块(一般来说就是大括号里包起来的部分,可以省略大括号的for语句、if()语句等除外)中能够被使用。
函数作用域仅用于goto语句的标签,由于goto语句已经用得很少,在此笔者不再对函数作用域进行展开介绍。
存储类型
存储类型分为静态存储和动态存储,采用静态存储方式的变量一旦创建,其存储空间在整个程序的运行过程中都不会被释放。对于采用动态存储的变量来说,当进入该程序块(函数或复合语句等)时,建立该变量,分配存储空间,当退出该程序块时,撤销该变量,释放其存储空间。
在接下来的一部分内容里,笔者将按照不同的限定词来对各种常见情况进行分别描述。
不用限定词的情况
1 /*例2,不用限定词的情况*/ 2 #include<stdio.h> 3 int a=1;//a为全局变量,采用静态存储 4 int main() 5 { 6 int b=1;//b为局部变量,默认采用动态存储 7 return 0; 8 }
全局变量a采用静态方式存储,具有文件作用域,b采用动态方式存储,具有的是块作用域。
使用static
1 /*例3*/ 2 #include<stdio.h> 3 static int a=1; 4 int main() 5 { 6 static int b=1; 7 return 0; 8 }
在程序块外使用static来定义变量
如例3中的变量a。
对于全局变量来说,加不加static,该变量都采取静态方式来存储,但是加了static之后,该变量便变成了“内部变量”,即该变量只能在该文件内被使用。不加static的全局变量默认为“外部变量”,可以被其他文件在进行了引用申明(用extern,稍后介绍)后使用。
在程序块内使用static来定义变量
如例3中的变量b。
对于定义局部变量来说,如果不加任何修饰词,则该变量默认为自动变量,采取动态方式进行存储。在用static进行修饰的变量定义中,该变量将采取静态方式进行存储,而且其初始化在编译时进行,且只会进行一次。
但是,不管加不加static,在程序块内定义的变量都只具有块作用域。
使用extern
1 /*例4 part 1*/ 2 /*file 1.c*/ 3 #include<stdio.h> 4 int a=1; 5 static int b=1; 6 int main() 7 { 8 extern int c;//对于全局变量c做提前引用说明 9 printf("%d",c); 10 return 0; 11 } 12 int c=1;
1 /*例4,part 2*/ 2 /*file 2.c*/ 3 #include<stdio.h> 4 extern int a;//对全局变量a做引用申明 5 extern int b;//本行错误,因为b仅在file 1.c中有效 6 int main() 7 { 8 printf("%d",a); 9 return 0; 10 }
extern仅用于对全局变量进行引用声明,其中包括对在定义在使用处后边的全局变量做提前引用声明(如例4 part 1 第8行),也包括在一个文件中对另一个文件里定义的全局外部变量做引用声明(如例4 part 2 第4行)。
使用auto、register
使用auto可显示地声明自动变量,由于在程序块内声明的变量默认是auto的,所以auto更多地也就只是起到一个标记的作用了。
使用register可以将一些将被频繁使用的局部变量放到寄存器中,这样可以提高程序执行的效率。
原文地址:https://www.cnblogs.com/scwjy/p/10989629.html