变量从存在的时间(生存期)角度来分,可以分为动态储存方式和静态储存方式。
所谓静态存储方式是指在程序运行开始时由系统分配固定的储存空间的方式。
动态储存方式则是在程序运行期间根据需要进行动态的分配储存空间的方式。
存储空间分为3部分:(1)程序区(2)静态存储区(3)动态存储区。
在C语言中,每一个变量和函数都有两个属性:数据类型和数据的存储类别。
对数据型(如整型,字符型等):储存类别指的是数据在内存中的储存方式。具体包含四种:自动的(auto),静态的(static),寄存器的(register),外部的(extern)。根据变量的储存类别,可以知道变量的作用域和生存期。
1、auto变量
函数中的局部变量,如不专门声明为static储存类别,都是动态的分配存储空间(栈),数据存储在动态存储区中。
函数中的形参和在函数中定义的变量(包括在复合语句中定义的变量),都属此类,在调用该函数时,系统会给它们分配存储空间,在函数调用结束时,自动释放这些存储空间。
例:int f(int a) /*定义为f函数,a为形参*/
{
auto int b,c=3; /*定义b,c为自动变量*/
}
关键字auto可以省略,auto不写则默认为“自动存储类别”。
2、用stastic声明局部变量
有时希望函数中的局部变量的值在函数调用结束后不消失,即存储单元不释放。
这时就应指定局部变量为“静态局部变量”,用static进行声明。
例:
#include <stdafx.h> #include<stdio.h> int f(int a) { auto b=0; static int c=3; b=b+1; c=c+1; return(a+b+c); } void main() { int a=2,i; for(i=0;i<3;i++) { printf("%d\n",f(a)); } }
说明:(1)静态局部变量属于静态存储类别,在静态存储区内分配存储单元。在函数整个运行期间都不释放,而自动变量属于动态存储类别,占动态存储空间而不占静态存储空间,函数调用结束后释放。
(2)对静态局部变量是在编译时赋初值的,即只赋初值一次,在程序运行时已有初值。
(3)若在定义局部变量时不赋初值的话,则对静态局部变量来说,编译时自动赋初值0(对数值型变量)或空字符(对字符型变量),对自动变量来说,不赋初值则它的值是一个不确定的值。
(4)虽然静态局部变量在函数调用结束后仍然存在,但其他函数是不能引用它的。
例:输出从1到5的阶乘值。
#include <stdafx.h> #include<stdio.h> int fac(int a) { static int f=1; f=f*a; return(f); } void main() { int i ; for(i=1;i<=5;i++) { printf("%d!=%d\n",i,fac(i)); } }
3、register变量
一般情况下,变量存放在内存中。
但若一些变量使用过于频繁则会浪费很多时间(cpu处理数据与内存读取数据有时间差)。
为提高程序执行效率,C语言允许将局部变量的值放在CPU寄存器中,需要时直接取出参加运算,不必再到内存中去存取。
这种变量称为寄存器变量,用关键字register作声明。
例:输出1到n阶乘的值。
#include <stdafx.h> #include<stdio.h> int fac(int n) { static int i ,f=1; for(i=1;i<=n;i++) { f*=i; } return(f); } void main() { int i,n; scanf("%d",&n); for(i=1;i<=n;i++) { printf("%d!=%d\n",i,fac(i)); } }
4、用extern声明外部变量
有时要用extern来声明外部变量,以扩展外部变量的作用域。
例:
#include <stdafx.h> #include<stdio.h> int max(int x,int y) { int z; z=x>y?x:y; return(z); } void main() { extern int A,B; printf("%d\n",max(A,B)); } int A=13,B=8;
其实extern的作用就是告诉编译器读到AB时知道其为全局变量,其值可能在程序的任意一个地方。