首先介绍三个概念:
(1)作用域:作用域描述了程序中可以访问一个标识符的一个或多个区域。
一共有三种作用域:代码块作用域、函数原型作用域和文件作用域
a.代码块作用域:一个代码块是包含在开始花括号和对应结束花括号之间的一段代码,在代码块内定义的变量具有代码块作用域,从该变量定义的地方到包含该定义的代码块的结尾该变量均可见。
传统上,具有代码块作用域的变量都必须在代码块的开始处进行声明,c99放宽了这一规则,允许在代码块的任何位置声明变量,譬如说for循环的控制部分,类似的还有while循环、do while循环等。
以for循环为例:
for(int i = 0; i < 100; i++) ;
对于变量i来说,只在for循环中可见,离开了for循环,i就不可见了。
b.函数原型作用域:适用于函数原型中使用的变量名。函数原型作用域从变量定义处一直到原型声明的末尾。
int test(int a, int b);
以上述声明为例,变量a、b的作用域只有上面这一行声明。这意味着,在处理一个函数原型的参数时,它所关心的只是参数的类型,使用什么名字是无关紧要的。
c.文件作用域:一个在所有函数之外定义的变量具有文件作用域,具有文件作用域的变量从它定义处到包含该定义的文件结尾处都是可见的。文件作用域变量也被称为全局变量。
(2)链接
一个C变量具有下列链接之一:外部链接、内部链接或空链接
a.空链接:具有代码块作用域或函数原型作用域的变量具有空链接,意味着它们是由其定义所在的代码块或者函数原型所私有的。
b.外部链接、内部链接:具有文件作用域的变量可能有内部链接或者外部链接。一个具有外部链接的变量可以在一个多文件程序的任何地方使用,一个具有内部链接的变量可以在一个文件的任何地方使用。
如何区分外部链接和内部链接呢?声明前面有无static。
(3)存储时期
一个C变量具有以下两种存储时期之一:静态存储时期和自动存储时期
静态存储时期:如果一个变量具有静态存储时期,它在程序执行期间将一直存在,具有文件作用域的变量具有静态存储时期;
自动存储时期:具有代码块作用域的变量一般具有自动存储时期。在程序进入定义这些变量的代码块时,会为这些变量分配内存,当推出这个代码块时,分配的内存将被释放。
下面介绍几种变量:
(1)自动变量
属于自动存储类的变量具有自动存储时期、代码块作用域和空链接,默认情况下,在代码块和函数的头部定义的任何变量都属于自动变量。然而,也可以像下面所示显式地使用关键字auto
int main() { auto int a; }
为了有意覆盖一个外部函数定义时,或者为了表明不能将变量改变成其他存储类的时候,可以使用auto。
自动变量的初始化:除非显式地初始化自动变量,否则它不会被自动初始化,如果未初始化,它的初值是先前占用分配给它的空间的任意值。
(2)寄存器变量
通常的变量被存储在计算机内存中,如果幸运的话可以被存储在CPU寄存器中,可以比普通变量更快地被访问和操作。因为寄存器变量多是被存在一个寄存器中而非内存中,因此无法获得寄存器变量的地址,和自动变量一样,它们都具有代码块作用域、空链接以及自动存储时期。
使用关键字register可以声明寄存器变量,但是即使声明了,变量也不一定会被存在寄存器中。
(3)具有代码块作用域的静态变量
这种变量是具有代码块作用域,兼具静态存储的局部变量。这些变量和自动变量具有相同的作用域,但当包含这些变量的函数完成工作时,它们并不消失。这些变量具有代码块作用域,空链接,但是却有静态存储时期,从一次函数调用到下一次调用,计算机都记录着它们的值,这样的变量通过存储类说明符static在代码块内声明创建。
(4)具有外部链接的静态变量
具有外部链接的静态变量具有文件作用域、外部链接和静态存储时期。这一变量被称为外部变量。把变量的定义声明放在所有函数之外,即创建了一个外部变量。如果其他文件使用该外部变量,则需要extern关键字来再次声明它。
外部变量可以被显式地初始化,但是不同于自动变量,如果不对外部变量进行初始化,它们会被赋值为0。外部变量只可以用常量表达式来初始化文件作用域变量。
具有extern关键字是一个引用声明而非定义声明,引用声明不会分配空间。
(5)具有内部链接的静态变量
这种存储类的变量具有静态存储时期、文件作用域以及内部连击,通过使用存储类说明符static在所有函数外部进行定义来创建一个这样的变量。
下面是两个类型限定词:const和volatile
(1)类型限定词const:如果变量声明中带有关键词const,则不能通过赋值、增量或减量运算来改变该变量的值,只可以通过初始化进行赋值
指针使用const有以下两种情况:
const float *pf //pf指向一个常量浮点数值,但是pf本身的值可以改变,譬如说,它可以指向另外一个const值 const * float pt; //pt是一个常量指针,它必须指向同一个地址,但所指向的值可以改变 const float * const ptr; //ptr必须总是指向同一个位置,并且它指位置存储的值也不能改变
这种新关键字的一种常见用法是声明作为函数形式参数的指针,这样指针只是让函数访问值。
如果在文件之间使用const数据,可以使用两个策略:
a.遵循外部变量的惯用规则:在一个文件中进行声明,在其他文件中进行引用声明(关键字extern)
b.将常量放在一个include文件中,譬如说constant.h。而且还必须是静态外部存储类:如果不使用关键字static,在多个文件中都包含头文件,导致每个文件都有同一标识符的定义声明(有些编译器不允许这样做)。
(2)类型限定词volatile:
限定词volatile告诉编译器该变量除了可被程序修改以外还可被其他代理改变,典型地,它被用于硬件地址和其他并行程序共享的数据。
原文地址:https://www.cnblogs.com/mmmmmmmelody/p/10354742.html