C语言变量的存储类别内存中供用户使用的存储空间分为代码区与数据区两个部分。
变量存储在数据区,数据区又可分为静态存储区与动态存储区。
静态存储是指在程序运行期间给变量分配固定存储空间的方式。
如全局变量存放在静态存储区中,程序运行时分配空间,程序运行完释放。
动态存储是指在程序运行时根据实际需要动态分配存储空间的方式。
如形式参数存放在动态存储区中,在函数调用时分配空间,调用完成释放。
对于静态存储方式的变量可在编译时初始化,默认初值为O或空字符。
对动态存储方式的变量如不赋初值,则它的值是一个不确定的值。
在C语言中,具体的存储类别有自动(auto)、寄存器(register)、静态(static)及外部(extern)四种。
静态存储类别与外部存储类别变量存放在静态存储区,自动存储类别变量存放在动态存储区,寄存器存储类别直接送寄存器。
变量存储类别定义方法:存储类别类型变量表;例如:(1)a,b,c为整型自动存储类别变量:auto int a,b,c;(2)x,y,z为双精度型静态存储类别变量:static double x,y,z;1、变量有哪些存储类型?变量的存储类型由“存储类型指明符”来说明。
存储类型指明符可以是下列类键字之一:autoregisterexternstatic下面是详细的解释:auto 存储类指明符--用于说明具有局部作用域的变量,它表示变量具有局部(自动)生成期,但由于它是所有局部作用域变量说明的缺省存储类指明符,所以使用得很少。
要注意的是,所有在函数内部定义的变量都是局部变量,函数内部定义的变量其作用域只在函数内部。
它的生存期为该函数运行期间,一旦离开这个函数或这个函数终止,局部变量也随之消失。
register 存储类指明符--当声明了这个指明符后,编译程序将尽可能地为该变量分配CPU内部的寄存器作为变量的存储单元,以加快运行速度。
注意,寄存器与存储器是不同的。
寄存器一般在CPU内部,而存储器一般指外部的(比如内存条),CPU内部的寄存器其运算速度是很高的。
当寄存器已分配完毕,就自动地分配一个外部的内存。
它的作用等价于auto,也只能用于局部变量和函数的参量说明。
static 存储类指明符--表示变量具有静态生成期。
static变量的的特点是它离开了其作用域后,其值不会消失。
当回到该作用域之后又可以继续使用这个static变量的值。
例:利用static变量统计调用函数的次数int two(); /*函数原型说明*/void main(){int a=0;a=two(); /*a的值等于1*/a=two() /*a的值等于2*/a=two(); /*a的值等于3*/}int two(){static int b=0;/*定义了一个局部的static变量*/b ;return b;}如果不是一个static变量就不会有这个效果了int two(); /*函数原型说明*/void main(){int a=0;a=two(); /*a的值等于1*/a=two() /*a的值等于1*/a=two(); /*a的值等于1*/}int two(){int b=0;b ;return b;}变量a的值总是1,原因是在函数two()中,变量b不是一个static变量,其值随着离开two函数就消失了,当回到two函数时又被重新赋值0。
extern 存储类指明符--一般用在工程文件中。
在一个工程文件中因为有多个程序文件,当某一个变量在一个程序文件中定义了之后,如果在另一个程序文件中予以定义,就会出现重复定义变量的错误。
使用extern存储类型指明符就可以指出在该文件外部已经定义了这个变量。
extern变量的作用域是整个程序。
2、变量存储在内存的什么地方?1)变量可以存储在内存的不同地方,这依赖于它们的生成期。
在函数上部定义的变量(全局变量或static外部变量)和在函数内部定义的static变量,其生存期就是程序运行的全过程。
这些变量被存储在数据段(Data Segment)中。
数据段是在内存中为这些变量留出的一段大小固定的空间,它分为二部分,一部分用来初始化变量,另一部分用来存放未初始化的变量。
2)在函数内部定义的auto变量(没有用关键字static定义的变量)的生成期从程序开始执行其所在的程序块代码时开始,到程序离开该程序块时为止。
作为函数参数的变量只在调用该函数期间存在。
这些变量被存储在栈(stack)中。
栈是内存中的一段空间,开始很小,以后逐渐自动变大,直到达到某个预定义的界限。
3)当用malloc等函数给指针分配一个地址空间的时候,这个分配的内存块位于一段名为“堆(heap)”的内存空间中。
堆开始时很小,但调用malloc或clloc等内存分配函数时它就会增大。
堆可以和数据段或栈共用一个内存段,也可以有它自己的内存段,这完全取决于编译选项和操作系统。
与栈相似,堆也有一个增长界限,并且决定这个界限的规则与栈相同。
-----------------------------------------------------------------------------------------------------------------------------------------------------------------C语言变量的作用域和存储类型一、作用域和生存期C程序的标识符作用域有三种:局部、全局、文件。
标识符的作用域决定了程序中的哪些语句可以使用它,换句话说,就是标识符在程序其他部分的可见性。
通常,标识符的作用域都是通过它在程序中的位置隐式说明的。
1.局部作用域前面各个例子中的变量都是局部作用域,他们都是声明在函数内部,无法被其他函数的代码所访问。
函数的形式参数的作用域也是局部的,它们的作用范围仅限于函数内部所用的语句块。
void add(int);main(){int num=5;add(num);printf("%d\n",num); /*输出5*/}void add(int num){num++;printf("%d\n",num); /*输出6*/}上面例子里的两个num变量都是局部变量,只在本身函数里可见。
前面我们说了,在两个函数出现同名的变量不会互相干扰,就是这个道理。
所以上面的两个输出,在主函数里仍然是5,在add()函数里输出是6。
2.全局作用域对于具有全局作用域的变量,我们可以在程序的任何位置访问它们。
当一个变量是在所有函数的外部声明,也就是在程序的开头声明,那么这个变量就是全局变量。
void add(int);int num;main(){int n=5;add(n);printf("%d\n",num); /*输出6*/}void add(num) /*形式参数没有指定类型*/{num++;printf("%d\n",num); /*输出6*/}上面的main()和add()里面,并没有声明num,但是在最后输出的时候却要求输出num,这是由于在程序的开始声明了num是全局变量,也就是在所有函数里都可以使用这个变量。
这时候一个函数里改变了变量的值,其他函数里的值也会出现影响。
上面的例子输出都是6,因为在add()函数里改变了num的值,由于num是全局变量,就好象它们两个函数共用一个变量,所以在main()函数里的num也随之改变了。
3.文件作用域在很多C语言书上,都没有说明文件作用域,或者只是略微的提到,其实文件作用域在较大程序中很有作用(在多文件系统中)。
文件作用域是指外部标识符仅在声明它的同一个转换单元内的函数汇总可见。
所谓转换单元是指定义这些变量和函数的源代码文件(包括任何通过#i nclude指令包含的源代码文件)。
static存储类型修饰符指定了变量具有文件作用域。
static int num;static void add(int);main(){scanf("%d",&num);add(num)printf("%d\n",num);}void add(num){num++;}上面的程序中变量num和函数add()在声明是采用了static存储类型修饰符,这使得它们具有文件作用域,仅爱定义它们的文件内可见。
由于我们提到的大多数程序都只有一个编译文件组成,所以这种写法没有实际意义。
但是实际工程上的文件有很多,它们不是由一个人写成的,由很多人共同完成,这些文件都是各自编译的,这难免使得某些人使用了一样的全局变量名,那么为了以后程序中各自的变量和函数不互相干扰,就可以使用static修饰符,这样在连接到同一个程序的其他代码文件而言就是不可见的。
二、变量存储类型前面我们说了,声明变量时用如下类似的形式:int num;float total;它们都没有存储类型修饰符,我们在声明时也可以通过存储类型修饰符来告诉编译器将要处理什么类型的变量。
存储类型有以下四种:自动(auto)、静态(static)、外部(extern)、寄存器(regiser)。
1.自动存储类型自动存储类型修饰符指定了一个局部变量为自动的,这意味着,每次执行到定义该变量的语句块时,都将会为该变量在内存中产生一个新的拷贝,并对其进行初始化。
实际上,如果不特别指明,局部变量的存储类型就默认为自动的,因此,加不加auto都可以。
main(){auto int num=5;printf("%d\n",num);}在这个例子中,不论变量num的声明是否包含关键字auto,代码的执行效果都是一样的。
函数的形式参数存储类型默认也是自动的。
2.静态存储变量前面已经使用了static关键字,但是对于局部变量,静态存储类型的意义是不一样的,这时,它是和自动存储类型相对而言的。
静态局部变量的作用域仍然近局限于声明它的语句块中,但是在语句块执行期间,变量将始终保持它的值。
而且,初始化值只在语句块第一次执行是起作用。
在随后的运行过程中,变量将保持语句块上一次执行时的值。
看下面两个对应的程序:/*1.C*/ /*2.C*/int add(); int add();main() main(){ {int result; int result;result=add() result=add();printf("%d ",result); printf("%d ",result);result=add(); result=add();printf("%d ",result); printf("%d ",result);result=add(); result=add();printf("%d",result); printf("%d",result);} }int add() int add(){ {int num=50; static int num=50;num++; num++;return num; return num;} }上面两个源文件,只有函数add()里的变量声明有所不同,一个是自动存储类型,一个是静态存储类型。