存储类 名词:作用域、链接和存储时期
一、作用域:描述了程序中可以访问一个标识符的一个或多个区域,一个c变量的作用域可以是代码块作用域,函数原型作用域或者文件作用域。
下面代码变量prt和tri的作用域都是直到结束花括号的作用域。
double block(double prt)
{
doubletri=0.0;
//*******实现部分**********
returntri;
}
在内部代码块中声明变量,其作用域只局限于该代码块。
在传统上,具有代码块作用域的变量都必须在代码块开始处进行声明。C99放宽了这一规则,允许在一个代码块的任何位置处声明变量,一个新的可能是变量声明可以出现在for 循环的控制部分。即:
for(int i=0;i<10;i++)
printf("Ac99 feature:i=%d\n",i);
C99的反代码概念扩大到包括由for 循环,while循环、do while循环或者if 语句控制的代码。注意:变量i的作用域局限在这个for 循环中。
2、函数原型作用域
其适用于函数原型中使用的变量名。
int comp(int mouse ,int large);
其作用域从变量定义一直到原型声明的末尾。意味着:编译器在处理一个函数原型的参数时,它所关心的只是参数的类型,名称是无关要紧的,不需要使它们的函数定义中使用的变量名保持一致。
3、一个在函数之外定义的变量具有文件作用域(filescope),
#include<stdio.h>
int unit=0;//具有文件作用域
void critics(void);
int main(void){
//**********
}
void critics(void){
//*********
}
这是变量unit 函数critrcs()和main()都使用它,不上被一个函数使用。文件作用域变量也称为全局变量(global variable)
二、链接
外部链接(extetnal linkage)、内部链接(internal linkage)或空链接(no linkage)
具有代码作用域和函数原型作用域的变量具有空链接,意味着:它们由其所定义的代码块和函数原型所私有。具有文件作用域可能有内部或外部链接。一个具有外部链接的变量可以在一个多文件程序的任何地方使用。一个具有内部链接的变量可以在一个文件的任何地方使用。
int gaint=2;//文件作用域,外部链接
static int solo =3;//文件作用域,内部链接
int main(void)
{
//实现部分
}
和该文件属于同一程序的其它文件可以使用变量gaint,变量solo是该文件私有的,但是可以被该文件中的任一函数使用。
三、存储时期
C有两种:静态存储时期(staticstorage duration),自动存储时期(automatic storage duration)
一个变量具有静态存储时期,它在程序执行期间一直存在,具有文件作用域的变量具有静态存储时期。
具有代码块作用域一般具有自动存储时期,在程序进入定义这些变量的代码块时,将为这些变量分配内存;当退出这些代码块时,分配的内存将被释放。
四、静态变量(static variable)
1、具有代码块作用域的静态变量
#include<stdio.h>
#include<stdlib.h>
void stat(void);
int main(void)
{
int count;
for(count=1;count<=3;count++){
printf("Here comes iteration %d:\n",count);
stat();
}
system("pause");
return 0;
}
void stat(void)
{
int fade=1;//是该函数的一部分,每次调用都会执行它,是运行时的动作。
static int stay=1;//不是函数的一部分,调试程序逐步运行会发现看起来跳过该步,
//静态变量和程序调入内存时就已经到位,把这个语句放在该函数是为了编译器只有该函数
//才能看到该变量,它并不是在运行时执行的语句。
printf("fade= %d and stay=%d\n",fade++,stay++);
}
结果:
静态变量stay 记得它的值曾被加1,而变量fade每次重新开始,初始化不同:在每次调用stat()函数时fade都被初始化,而stay只在编译stat()时被初始化一次。
2、具有外部链接的静态变量
这类变量为外部变量(externel variable).把变量放在所有函数之外,即创建了一个外部变量。为了使程序更加清晰,可以在使用了外部变量的函数中通过使用externel关键字再次声明它。如果该变量是在别的文件定义中,使用externel来声明是必须的。
int tern=1;
int main()
{
externint tern;//使用在其他地方定义的tern变量
}
这里,tern声明了两次,第一次声明为变量留出了存储空间,它构成了变量的定义,第二次只是告诉编译器要使用先前的定义的变量tern,它不是一个定义,为引用声明。关键字extern声明不是一个定义,它指示编译器参考其他地方。
extern int tern;
int main(void)
{
}
以上例为,编译器假定tern真正的定义在其他地方,也许是在另一个文件中,这样的声明不会引起空间分配。因此,不要用extern来进行外部定义,它只是用来引用一个已经存在的外部定义。
3、具有内部链接的静态变量
通过使用说明符static在所有函数外部来进行定义,来创建这样一个变量
int traveler//外部链接
static int staythere; /*具有内部链接的静态变量*/
int main(void)
{
externint travaler;
externint stayhere;
}
对这个文件来说travaler和stayhome都是全局的,但只有travaler可以被其他文件中的代码使用,使用extern的两个声明表明main()在使用两个全局变量。但stayhere仍具有内部链接。