第一角度:分清变量的存储类型。
1 变量的存储类型一般分为:静态存储类型和动态存储类型。
1.1 静态存储类型变量
静态存储类型变量通常是在变量定义时 (“在程序进入 main()之前创建”)就分定存储单元并一直保持不变, 直至整个程序结束(“在main()结束之后销毁”),也正因为如此,我们在创建静态存储变量的同时如果没有给它赋初值,那么编译器会自动将0转换为所需的数据类型来初始化它。
例如:定义全局变量:int a,不加以初始化,那么,编译器会自动赋值a=0;而如果是float a,编译器会自动赋值a=0.0;
1.1.1 静态存储类型的变量有哪些?
1.1.1.1 外部变量
外部变量的的类型说明符为extern。外部变量和全局变量是对同一类变量的两种不同角度的提法。全局变量是从它的作用域提出的,外部变量从它的存储方式提出的,表明了它的生存期。因其使用方法和注意点跟全局变量一致,所以在下面介绍全局变量时再进一步详细说明。
1.1.1.2 静态变量
1、静态变量的声明与定义
静态变量的类型说明符是static。静态变量当然是属于静态存储方式,但是属于静态存储方式的量不一定就是静态变量。
例如:外部变量虽属于静态存储方式,但不一定是静态变量,必须由static加以定义后才能成为静态外部变量,或称静态全局变量。
2、静态变量的分类
1)静态局部变量
(1)定义:在局部变量的声明前再加上static说明符就构成静态局部变量。
例如:
Int d ( int e )
{
int f;
}
希望局部变量是静态时,则按照*这样改即可:
int d ( int e )
{
*static int f;
}
(2)在使用静态局部变量过程中要注意以下几点:
静态局部变量的生存期为整个源程序。静态局部变量在代码块内定义,但不象自动变量那样,当调用时就存在,退出函数时就消失。静态局部变量始终存在着,也就是说它的生存期为整个源程序。
‚静态局部变量其作用域仍与自动变量相同。静态局部变量的生存期虽然为整个源程序,但是其作用域仍与自动变量相同,即只能在定义该变量的函数内使用该变量。退出该函数后,尽管该变量还继续存在,但不能使用它。
ƒ允许对构造类静态局部量定义的同时赋以初值。若未赋以初值,则由系统自动赋以相应数据类型的0值。
构造数据类型是根据已定义的一个或多个数据类型用构造的方法来定义的。也就是说,一个构造类型的值可以分解成若干个“成员”或“元素”。每个“成员”都是一个基本数据类型或又是一个构造类型。在C语言中,构造类型有以下几种:数组类型、结构体类型、共用体(联合)类型。
④对基本类型的静态局部变量若在定义时未赋以初值,则系统自动赋予相对应数据类型的0值。对基本类型的静态局部变量若在说明时未赋以初值,则系统自动赋予0值。而对自动变量不赋初值,则其值是不定的。根据静态局部变量的特点,可以看出它是一种生存期为整个源程序的量。虽然离开定义它的函数后不能使用,但如再次调用定它的函数时,它又可继续使用,而且保存了前次被调用后留下的值。因此,当多次调用一个函数且要求在调用之间保留某些变量的值时,可考虑采用静态局部变量。虽然用全局变量也可以达到上述目的,但全局变量有时会造成意外的副作用,因此仍以采用局部静态变量为宜。
例如:
main()
{
int i;
static int a[6]={1,2,3,4,5,6};
void f();/*函数说明*/
for(i=1;i<=5;i++)
f();/*函数调用*/
}
void f()/*函数定义*/
{
auto int j=0;
++j;
printf("%d/n",j);
}
程序中定义了函数f,其中的变量j说明为自动变量并赋予初始值为0。当main中多次调用f时,j均赋初值为0,故每次输出值均为1。
现在把j改为静态局部变量,程序如下:
main()
{
int i;
static int a[6];
void f();
for(i=1;i<=5;i++)
f();
}
void f()
{
static int j=0;
++j;
printf("%d/n",j);
}
由于j为静态变量,能在每次调用后保留其值并在下一次调用时继续使用,所以输出值成为累加的结果。
对于静态数组a[6],因为它是静态存储类型的变量,所以我们在首次定义它时,如果没有赋值的话,编译器会自动给它赋值为相应类型的0,编译器此时也要给它分配内存单元,所以,你必须指明数组有大,否则编译器无法确定你要多大内存,从而造成错误编译。
拓展:只要是静态存储类型的变量,你在初始化它时都必须给个确定的值给它,总之就是要保证编译器能够识别你定义的这个变量有多大,从而确定这个量要多大的内存并且加以分配。
2)静态全局变量
(1)静态全局变量的定义
全局变量(外部变量)的说明之前,再冠以static就构成了静态的全局变量。全局变量本身就是静态存储方式,静态全局变量当然也是静态存储方式。这两者在存储方式上并无不同。
这两者的区别在于非静态全局变量的作用域是整个源程序,当一个源程序由多个源文件组成时,非静态的全局变量在各个源文件中都是有效的。而静态全局变量则限制了其作用域,即只在定义该变量的源文件内有效,在同一源程序的其它源文件中不能使用它。
由于静态全局变量的作用域局限于一个源文件内,只能为该源文件内的函数公用,因此可以避免在其它源文件中引起错误。
从以上分析可以看出,把全局变量改变为静态变量后是改变了它的作用域,限制了它的使用范围。
(2)使用静态全局变量需要注意的地方
把全局变量改变为静态变量后,它的作用域局限于定义它的源文件里,可以防止其他文件调用它。
1.2 使用动态存储类型变量
动态存储变量动态存储变量是在程序执行过程中,使用它时才分配存储单元,使用完毕立即释放。
1.2.1 动态存储类型的变量有哪些?
1.2.1.1 自动变量
自动变量的类型说明符为auto:C语言规定,函数内凡未加存储类型说明的变量均视为自动变量,也就是说自动变量可省去说明符auto。
在不同的代码块内,允许同名自动变量。因为不同代码块内自动变量其作用域仅限于定义该变量的代码块内。离开其所在的代码块后,变量立刻死亡,下次出现时已经不是同一个的了,只是名字相同罢了。
例如:
int kv(int a)
{
auto int x,y;
{
auto char c;
}/*c的作用域*/
……
}/*a,x,y的作用域*/
其生存期也只在相应的代码块内。自动变量属于动态存储方式,只有在使用它,即定义该变量的代码块被调用时才给它分配存储单元,开始它的生存期。代码块调用结束,释放存储单元,结束生存期。因此函数调用结束之后,自动变量的值不能保留。
再看一个例子,以加深理解:
main()
{
auto int a,s,p;
printf("/ninput anumber:/n");
scanf("%d",&a);
if(a>0)
{
s=a+a;
p=a*a;
}
printf("s=%d p=%d/n",s,p);
}
{
auto int a;
printf("/ninput anumber:/n");
scanf("%d",&a);
if(a>0)~~1
{
auto int s,p;
s=a+a;
p=a*a;
}
printf("s=%d p=%d/n",s,p);
}
s,p是在代码块句内定义的自动变量,只能各自的代码块内生存。而代码块~~1中,它们却是退出该程序块复合语句之后用printf语句输出s,p的值,这显然会引起错误。
1.2.1.2 寄存器变量
1、寄存器变量的定义
上述各类变量都存放在存储器内, 因此当对一个变量频繁读写时,必须要反复访问内存储器,从而花费大量的存取时间。
为此,C语言提供了另一种变量,即寄存器变量。这种变量存放在CPU的寄存器中,使用时,不需要访问内存,而直接从寄存器中读写, 这样可提高效率。
寄存器变量的说明符是register。
对于循环次数较多的循环控制变量及循环体内反复使用的变量均可定义为寄存器变量。
求∑200i=1i
main()
{
register i,s=0;
for(i=1;i<=200;i++)
s=s+i;
printf("s=%d/n",s);
}
本程序循环200次,i和s都将频繁使用,因此可定义为寄存器变量
2、使用寄存器变量需要注意的地方
使用寄存器变量需要注意以下几点:
1)只有局部自动变量和形式参数才可以定义为寄存器变量。
2)在Turbo C,MS C等微机上使用的C语言中,实际上是把寄存器变量当成自动变量处理的。在Turbo C,MS C等微机上使用的C语言中,实际上是把寄存器变量当成自动变量处理的。因此速度并不能提高。而在程序中允许使用寄存器变量只是为了与标准C保持一致。
3)寄存器变量的个数是有限的。即使能真正使用寄存器变量的机器,由于CPU中寄存器的个数是有限的,因此使用寄存器变量的个数也是有限的。
第二角度:分清变量的变量作用域
2 变量一般可以分为两种,全局变量和局部变量。
2.1 全局变量
2.1.1 全局变量的定义
全局变量也称为外部变量,必须在所有的函数之外,且只能定义一次。如在定义时没初始化,由于它是静态存储方式,系统自动初始化为与定义的数据类型相对应的初始值0。
其一般形式为:
[extern]类型说明符变量名,变量名…
其中方括号内的extern可以省去不写。
例如:
#include<stdio.h>
extern int a,b;
main(){......}
等效下面:
#include<stdio.h>
int a,b;
main(){......}
2.1.2 全局变量的作用
从函数中得到多个返回值。全局变量的使用增加了函数间数据联系的渠道,由于在同一文件中的所有函数都能使用全局变量,所以可以利用全局变量从函数中得到一个以上的返回值,而使用return只能返回一个值。
例:求某班成绩的平均分,最高分和最低分。
#include<stdio.h>
float max=0,min=100;
float average(int n);
int main(void)
{
int m;float ave2;
scanf("%d",&m);
ave2=average(m);
printf("%f,%f,%f\n",ave2,max,min);
return 0;
}
float average(int n)
{int i;float s,ave1,sum=0;
for(i=1;i<=n;i++)
{scanf("%f",&s);
if(s>max)max=s;
if(s<min)min=s;
sum=sum+s;}
ave1=sum/n;
return(ave1);}
由float average(int n)函数可以得到max,min,ave1变量,注意,max,min这两个变量时由于它生存期是整个程序运行过程,所以它们会一直存在,并且它又是全局变量,整个源程序里的每个函数都可以使用它们用来存储数据。
这样,当在float average(int n)中对他们两个进行赋值运算时,它们的数据会一直保存下来,供主函数调用。
如此看来,就可以通过float average(int n)来得到所以可以利用全局变量从函数中得到三个返回值,分别是全局变量max和min,还有使用return返回值ave1。
2.1.3 使用全局变量需要注意的地方
(1)有效范围:文件作用域。
1)任何代码块之外声明的标识符“即变量”都具有文件作用域,文件作用域表示该变量从它们声明之处直到它所在的源文件结尾处都是可以访问的。通俗来讲,就是说它的有效范围是从定义变量的位置开始到本源文件结束,一直占内存,它不属于哪一个函数,它属于一个源程序文件。其作用域是整个源程序。
比如,有两个源文件,f1.c和f2.c
f1.c
#include<stdio.h>
float max=0,min=100;
float average(int n);
int main(void)
{
int m;float ave2;
scanf("%d",&m);
ave2=average(m);
printf("%f,%f,%f\n",ave2,max,min);
return 0;}
f2.c
#include<stdio.h>
extern float max,min/*将f1.c的全局变量链接到f2.c中来,这样f2.c中才可以使用它们*/
float average(int n)
{int i;float s,ave1,sum=0;
for(i=1;i<=n;i++)
{scanf("%f",&s);
if(s>max)max=s;
if(s<min)min=s;
sum=sum+s;
}
ave1=sum/n;
return(ave1);
}
那么,max,min作为全局变量,其作用域是源程序文件f1.c,它在f2.c是无效的,除非用extern声明其为外部链接属性,才可以在f2.c这个源程序文件里访问他们。
2)在同一源文件中,允许全局变量和局部变量同名。在局部变量的作用域内,全局变量不起作用。
若全局变量与局部变量同名,则全局变量被屏蔽:
#include<stdio.h>
int a=3,b=5;
max(int a,int b)
{int c;
c=a>b?a:b;
return c;
}
int main(void)
{int a=8;
printf("max=%d",max(a,b));
return 0;
}
运行结果:max=8
分析:main中因为指明a=8,同时在调用max函数时8传递过去,所以在max中,,传过去的数据8代表了max函数中的形参a,它会覆盖全局变量a,b还是使用全局变量b的值。
3)当一个源程序由若干个源文件组成时,在一个源文件中定义的外部变量在其它的源文件中也有效。
例如:有一个源程序由源文件F1.C和F2.C组成
F1.C
#include<stdio.h>
char c;/*外部变量定义*/
main()
{
……
}
F2.C
#include<stdio.h>
extern char c;/*外部变量说明*/
func(int x)
{
……
}
假设在F1.C和F2.C两个文件中都要使用c变量。在F1.C文件中把c定义为外部变量。
在F2.C文件中用extern把c变量说明为外部变量,表示这些变量已在其它源程序文件中定义,编译系统不再为它们分配内存空间。
对构造类型的外部变量,如数组等可以在说明时作初始化赋值,若不赋初值,则系统自动定义它们的初值为0。
拓展:函数名其实也具有文件作用域函数名其实也具有文件作用域,其实函数名本身不属于任何代码块,怎么才算包含在代码块内呢?“必须是处于“{}”内的变量。但是,任何函数中都禁止定义和声明都函数。这也就导致了“函数名”永远处于任何代码块之外,因此,函数名本身不属于任何代码块,,,类似于外部变量。
调用这个函数的函数时,如果他有返回值,那你就可以得到它的返回值:
比如:
int b(int c)
{...}
int h(int i)
{
int j,k;
k=b(j);
}
main()
{
int d,g;
g=b(d);
}
只要在头文件中编写并通过#include指令包含到其他文件中的声明就好像他们是直接写在那些文件中那样。
因此,你在整个源程序都可以调用这个函数,类似于全局变量只要在其他源文件中声明后就可以使用那样
(2)外部变量声明不能再赋初始值
外部变量在定义时就已分配了内存单元,外部变量定义可作初始赋值,外部变量声明不能再赋初始值,只是表明在函数内要使用某外部变量。
例如:
正确用法如下:
#include<stdio.h>
int a=3,b=6;
int zuoyongyu()
{
extern int a,b;
int c=0;
c=a+b;
......
}
main(){......}
以下加*处是错误之处:
#include<stdio.h>
int a=3,b=6;
int zuoyongyu()
{
*extern int a=3,b=6;*
int c=0;
c=a+b;
......
}
main(){......}
(3)函数内使用该全局变量时必须加以声明,局变量的说明符为extern。在函数中使用全局变量,应作全局变量说明。而全局变量生命明出现在要使用该外部变量的各个函数内,在整个程序内,可能出现多次。
外部变量声明的一般形式为:extern 类型说明符 变量名,变量名,…;
另外,*在一个函数之前定义的全局变量,在该函数内使用可不再加以说明*:
例如:
#include<stdio.h>
int a,b;
int zuoyongyu()
{*extern int a,b;
int c=0;
c=a+b;
......}
main(){......}
也可以这样
#include<stdio.h>
int a,b;
int zuoyongyu()
{/*不用*extern int a,b;*/
int c=0;
c=a+b;
......}
main(){......}
*但在一个函数之后定义的全局变量,在该函数内使用必须加以说明*
例如:
#include<stdio.h>
int zuoyongyu()
{extern int a,b;
int c=0;
c=a+b;
......}
main(){......}
int a,b;
绝对不可以这样,否则会编译错误
#include<stdio.h>
int zuoyongyu()
{int c=0;
**c=a+b;**
......}
main(){......}
int a,b;
2.1.4 全局变量的缺点
(1)全局变量在程序的执行过程中一直占用存储单元(因为它是静态存储类型的变量,生存期为整个程序)
(2)它使函数的通用性降低(这就导致必须在该全局变量作用范围内才能使用这个函数
(3)外部变量可加强函数模块之间的数据联系,但是又使函数要依赖这些变量,因而使得函数的独立性降低。
因此,从模块化程序设计的观点来,因在不必要时尽量不要使用全局变量。
2.2 局部变量
局部(内部)变量:位于一对花括号{}之间的所有语句组成一个代码块。而局部变量就是指在一个在某个代码块内部定义的变量,变量的定义必须在可执行语句之前,即进入{}后,首先要定义变量。
2.2.1 局部变量的有效范围
2.2.1.1 嵌套型代码块情况下
嵌套型代码块:变量只在本代码块的范围内有效,在此代码块之外不能使用这些变量。当代码块处于嵌套状态时,即代码块里还有代码块,此时声明于内层代码块的标识符(局部变量)的作用域到达该代码块的尾部终止。
然而,如果内层代码块中有一个变量的名字与外层代码块的一个标识符同名,那么内层那个标识符就将隐藏外层标识符,外层标识符无法在内层代码块中通过名字访问。
打个比方,大家都知道有两个同样名字的道士,都叫A,一个道士他住在中华大地某个地方,法力高深,可以护佑整个中华大地(作用域),另一个道士他住在燕京,法力可以护佑整个燕京的。
他们俩虽然名字一样,但你很清楚他们的地址,但是,因为你现在在燕京里,所以你只需要找燕京这个叫A的道士就可以庇护到你了,没必要那个更厉害的也叫A的道士,但是,如果燕京本来就没有道士,这时候,你就需要找那个可以庇护整个中华大地的A道士了。
可以理解为“就近原则”,谁里所执行部分程序近,那么就谁起作用。
看个例子:~~1和~~5中的i,在执行到变量~~5所在的代码块时,那么~~1虽然也是i,但它会被~~5的i隐藏起来,无法访问。
int i;~~1
int d(int e)~~2
{int f;~~3
int g(int h);~~4
...
{
int f,g,i;~~5
...
}
{
int i;~~6
...
}
}
int main()
{int j;
d(j);
...
}
2.2.1.2 非嵌套型代码块情况下
非嵌套型代码块:当代码块处于非嵌套状态时,声明于每个代码块中的变量无法被其他代码块访问,因为它们各自的作用域都局限于它们各自所在的代码块当中。
比如:~~5和~~6中的i,它们所在的代码块不可能同时存在,所以编译器可以把它们存储于同一个内存地址,当代码块5运行完,由于该代码块内定义的变量都是自动变量,代码块运行完就会立即释放其内所有自动变量的内存空间,因此,当执行到~~6所在的程序块时,该程序块里的变量就可以重新使用上一个程序块中使用的内存地址。
int i;~~1
int d(int e)~~2
{int f;~~3
int g(int h);~~4
...
{
int f,g,i;~~5
...
}
{
int i;~~6
...
}
}
int main()
{int j;
d(j);
...
}
2.2.2 使用局部变量需要注意的地方
(1)main函数中定义的变量也是局部变量,只在main函数中有效。主函数中定义的变量也只能在主函数中使用,不能在其它函数中使用。同时,主函数中也不能使用其它函数中定义的变量。因为主函数也是一个函数,它与其它函数是平行关系。
比如:
int d(int e)
{int f;
*f=j;*
...
}
int main()
{int j;
d(j);
...
}
主函数中的j变量是在主函数中定义的,那么,其它函数比如函数d中想访问j时就是非法的。
你可以这样做:
int d(int e)
{int f;
*f=e;*
...
}
int main()
{int j=1;
d(j);
...
}
这样改正后,实际上就是将主函数中j=1中这个数字1赋给函数d的形式参数,这样函数d内部需要使用到时就可以通过访问形式参数来得到需要的数值
(2)函数的形式参数也是局部变量
形式参数~~1 e和实际参数~~6 j
:
1、形参和实参的功能是作数据传送。发生函数调用时,主调函数把实参的值传送给被调函数的形参从而实现主调函数向被调函数的数据传送。
2、形式参数作为函数的局部变量,其作用域是函数最外层的那个作用域,怎样才算最外围内,这样:
int g(int h);~~3
{int f;
...
}
其中,形参h的作用域比f都还要大,因为它包含了整个“{}”的所有范围,而f的则是在定义它的语句之后。同时,不允许在函数内再定义一个跟形参同名的变量,无论它是何种类型,因为假设这样可以,那么,你在访问时,因为它们都一样的名字,你就会分不清你到底要访问的是哪一个变量定义的内存,因此,编译器也会扼止这种错误的可能性,一旦你在定义一个同名的变量编译器就会编译不通过。
引申开来,也就是说,在同样的作用域内,你不能企图用同样的变量名字来代表不同的内存空间,编译器是不允许的。就好像,在同一个家庭里生活(作用域相同)的两个人(两个不同的内存空间),你还给他们起一样的名字,那你叫这个名字时,他们中到底哪个人来回应你呢?这就冲突了,分不清楚的。
(3)形参变量e是属于被调函数d的局部变量,实参变量j是属于主调函数的局部变量,进入被调函数后,实参变量不能在被调函数中继续使用。
比如:
int d(int e)~~1
{int f;~~2
int g(int h);~~3
...
{
int f,g,i;~~4
...
}
{
int i;~~5
...
}
}
int main()
{int j;~~6 g(j);
d(j);
...
}
此外,还有个“原型作用域”,它是在函数原型中声明的形式参数变量的作用域,如:int g(int h);~~3,在原型中(和函数的定义不同),参数名字并非必须(可以这样:int g(int);)。
你可以随意给它任何名字,它不必与定义中的形参名匹配(可以这样:int g(int h或a或b或...);,也不必与实际调用时所传递的实参匹配,如主函数调用的格式为g(j),j是主函数中定义的变量,作为实参,明显,j跟int g(int h);~~3这个函数原型中的参数名是不同的。
总结来说,只要在函数原型中不重复使用同一个名字即可避免错误。
第三角度:链接属性决定某变量在各个文件中使用权限,类似于作用域
3 变量的链接属性一般分为三种:external(外部)、internal(内部)、“none(无)“无连接属性
3.1 external(外部)链接属性
external(外部)链接属性:无论声明多少次、位于几个源文件,只要加以声明,都表示同一个实体。
例如:
f1.c
int b;~~1
int c(int d)
{
int e;
int f(int g);
...
}
f2.c
extern int b;
int h(int i)
{
int j;
j=b;
...
}
b c f的链接属性都是external,所以,如果另一个源文件对所用到的变量比如b用extern关键字加以声明,并在该文件(f2.c)内使用它时,实际上访问的是f1.c文件中的所定义的b实体。f的链接属性之所以是external,是因为它是一个函数名,不属于任何程序块。在f1.c里调用f,实际上它将链接到其他文件中定义的f函数,因为f1.c中并没有关于f函数的定义,只是调用它而已。
其实上面也说过,现在再来说一下。全局变量就是具external(外部)链接属性,无论声明多少次、位于几个源文件,只要加以声明,都表示同一个实体。
例如:
f1.c
int b;~~1
int c(int d)
{
int e;
int f(int g);
...
}
f2.c
extern int b;
int h(int i)
{
int j;
j=b;
...
}
b c f的链接属性都是external,所以,如果另一个源文件对所用到的变量比如b用extern关键字加以声明,并在该文件(f2.c)内使用它时,实际上访问的是f1.c文件中的所定义的b实体。f的链接属性之所以是external,是因为它是一个函数名,不属于任何程序块。在f1.c里调用f,实际上它将链接到其他文件中定义的发函数,因为f1.c中并没有关于f函数的定义,只是调用它而已。
另外,如果某个变量(一般是全局变量或函数名)在正常情况下具有external属性时,只要在它前面加上static关键字,就可以使它的链接属性变为internal(内部):属于该属性的变量或函数在同一个文件内所有声明均指向同一个实体,但位于不同源文件的同样名称的声明则分属不同实体。
例如:
上面f1.c中的语句~~1,
改为:
static int b;
那么变量b就将为f1.c源文件所有,其他文件不能再访问它。
同样,也可以将f1.c中的函数改为:
static int(int c)
那么这时候其他文件也不能再调用它。
此时,如果在f2.c中再声明extern int b并成功的话,它代表的已经不是f1.c中所声明的那个b了,,而是除以上两个文件外的其它文件所定义的b.
3.2 internal(内部)链接属性
如果某个变量在正常情况下具有external属性时,只要在它前面加上static关键字,就可以使它的链接属性变为internal(内部):属于该属性的变量或函数在同一个文件内所有声明均指向同一个实体,但位于不同源文件的同样名称的声明则分属不同实体。
例如:
f1.c
int b;~~1
int c(int d)
{
int e;
int f(int g);
...
}
f2.c
extern int b;
int h(int i)
{
int j;
j=b;
...
}
上面f1.c中的语句~~1,
改为:
static int b;
那么变量b就将为f1.c源文件所有,其他文件不能再访问它。
同样,也可以将f1.c中的函数改为:
static int(int c)
那么这时候其他文件也不能再调用它。
此时,如果在f2.c中再声明extern int b并成功的话,它代表的已经不是f1.c中所声明的那个b了,,而是除以上两个文件外的其它文件所定义的b.
当然,我们一再强调变量名尽量不要重复,避免混淆,以上只不过是为了说明问题。
3.3 none(无)链接属性
“none(无)“无链接属性变量:没有链接属性的变量总是被当做单独的个体,也就是说该变量在不同代码块中的多个声明被当做不同的实体。”局部变量绝大部为无链接属性变量。static对none(无)“无连接属性”的变量的影响只是改变其生存期,但不改变变量的作用域。
比如:
int c(int d)
{
int e;~~1
{
int e;~~2
...
}
...
}
int h(int i)
{
int e;~~3
...
}
main()
{
int e;~~4
...
}
~~1,~~2,~~3,~~4中定义的e都是none无链接属性的,因此,它们都属于不同的实体,代表不同的内存单元。