全部博文(240)
分类: LINUX
2011-11-05 10:42:59
C语言中的一些说明和定义会用到存储类型这样一个概念,在C语言中存储类型会用到下述几个关键字:auto,static,register,extern。
看下面的简略图大家可以明确程序在进行存储时是分为三个区域的,分别为代码段,数据段和bss段,用于存储不同类型和状态的变量,而运行起来系统会再为其添加2个段,一个是堆,一个是栈,而我们手动进行的内存空间的申请是分配在堆区中的,栈区中存放的是程序在运行的过程中产生出来的一些临时信息和数据。我们依次来看一下这4个关键字的使用和区别。
auto存储类型说明的变量都是局部于某个程序范围内的,只能在某个程序范围内使用,通常在函数体内或函数中的复合语句里。C语言中,在函数体的某程序段内说明auto存储类型的变量时可以省略关键字auto。
如,有下述定义:
auto int k ; //说明一个auto整型的k变量
int K ; //省略了auto,说明一个auto整型的K变量
这2种定义方式是相同的,省略auto关键字也是我们常用的方式。
static:称为静态存储类型,在C语言中,既可以在函数体内,也可在函数体外说明static 存储类型的变量。
在函数体内说明的static 存储类型的变量也是一种局部变量,与auto最大不同点是:static存储类型的变量在内存中是以固定地址存放的,而不是以堆栈方式存放的;只要整个程序还在继续运行静态变量就不会随着说明它的程序段的结束而消失,static类型的变量只被初始化一次,且变量的值有继承性,如,有下面的程序段:
void fun()
{
int i = 0; *
i ++;
printf(“%d\n” , i );
}
int main()
{
fun();
fun();
fun();
return 0;
}
在主函数中3次调用fun函数,这时在终端上输出的内容为:
1
1
1
而我们将程序更改一下,将带有*的语句换作:
static int i = 0;
则程序在终端上的输出为:
1
2
3
这是static关键字的用法及特点。
register称为寄存器型,使用register关键词说明的变量主要目的是想将所说明的变量放入寄存器存储空间中,我们知道寄存器数量有限,且位于CPU的内部,这样可以加快程序的运行速度。但正因为寄存器的资源相对较少,所以编译器会判断程序所指定的需要放在寄存器中的内容有没有必要放入寄存器中去,也就是说,编译器来决定是否将指定内容放入到寄存器中,如果没有没有必要放入寄存器中,就使用auto类型作处理。综上所述,register是一个建议性关键字,编译器可以判断出是否去执行这样一个关键字,所以这个关键字在目前的用处相对地减少很多,大家了解这样一点。
extern称为外部参照引用型,使用extern说明的变量是想引用在其它文件中或在函数体外部已经声明过的变量
这里会涉及到一个概念,叫全局变量,指的是在所有的函数外部声明的变量,全部变量作用于全局,在整个程序运行期间值都被保存,全局变量的作用范围是从其定义处开始,直至程序结束,而extern关键字的作用是对全局变量进行引用的声明。如下面的程序:
int a = 1;
int main()
{
printf(“a = %d\n” , a);
return 0;
}
该程序可以成功运行,输出a的值为1,而如果改变一下:
int main()
{
printf(“a = %d\n” , a);
return 0;
}
int a = 1;
这样在进行编译时,编译器会报错,提示变量a没有定义。也就是说全局变量的作用范围是从定义处开始直至程序结束,而我们在该程序的基础上加上一句声明:
extern a;
int main()
{
printf(“a = %d\n” , a);
return 0;
}
int a = 1;
加上一个extern的说明后,该程序可以正常编译执行,在这里要注意extern关键字对于变量的类型说明可以省略,但对于变量的类型及值是没有任何改变权限的,也就是说在上面例子中的extern语言如果写成exter float a;或者是extern int a = 3;编译时会提示错误。
所以extern对于变量的类型及值没有任何更改的功能,只能是对于外部变量的定义进行一个引用的声明,换句话说,它扩大了外部变量的作用范围,所以extern是一个说明性关键字,而不是定义性的,说明与定义的区别我们可以来对比一下: