1 变量存储类型
如果要使用好变量,除了学习变量的运算性质和变量的存储形式以外,变量的生存时间和变量在内存中的存储位置也应是我们学习C语言时应该深入了解的内容之一。
在前面学习数组时,我们就已经了解到:变量应该要从“数据类型”和“存储类型”两个方面才能比较深入地进行描述,由于前面我们已经学习了“数据类型”,所以本节主要学习“存储类型”的基本知识。
变量的存储类型主要可以分为四种,即:动态存储、外部存储、静态存储和寄存器变量,C语言中分别用auto、extern、static、register加以说明。存储类别说明符主要是用来告诉编译程序,其后的变量应该如何存储。
如果从变量的生存时间上考察变量,我们可以表示为:
静态存储变量:在程序运行期间分配固定的存储空间
变量的生存周期
动态存储变量:程序运行时根据需要进行动态分配存储空间的方式
变量的存储类型说明要放在变量的数据类型说明之前,即以下形式:
存储类型 数据类型 变量名
2 局部变量存储方式:
1) 自动变量(auto型)
格式:auto 类型名 变量名
动态变量存储在动态存储区中,主要是指函数的动态局部变量和形式参数。
动态变量在函数调用开始就动态分配内存单元,在函数调用结束时,由系统收回并释放其内存空间。
因为普通的局部变量均隐含地被认为是auto型,所以一般很少使用auto说明符。
例: auto int b=3; (注意:auto可以省略或默认类别为auto)
如上可写成 int b=3;
2) 局部静态变量
静态变量存储在静态数据区,在其所在的函数和程序中是永久变量,所以如果想在调用函数后保留变量值,下次调用时继续使用,则应用静态存储。
格式:static 类型名变量名
【例8.6.1】静态变量示例
int f(b)
int b;
{
auto int a=0;
staticint c=3; // 分析: b c
a=a+1;c=c+1; // 第一次开始: 0 3
return(a+b+c);} // 第一次结束: 1 4
main() // a+b+c=7
{
int b=2,i; // 第二次开始: 0 4
for(i=0;i<3;i++) // 第二次结束: 1 5
printf(" %d ",f(b) ); // a+b+c=8
} // 第三次开始: 0 5
// 第三次结束: 1 6
// a+b+c=9
说明:
(1) 局部静态变量属静态存储类别。(程序运行期间存储数据不释放)而自动变量不占自动空间(调用结束释放)。
(2) 局部静态变量在编译初期赋值,以后只保留上次调用时值,而自动变量每调用一次重新赋值。
(3) 在定义局部变量时如不赋初值。
静态变量:自动为0;
动态变量:值不固定(因为每次结束释放,下次分配)。
(4) 在第九章讲到数组时,会介绍到只有全局变量和局部静态变量才可以对数组初始化。
(5) 局部静态变量使用情况。
a.需保留上一次调用结束时值;
b.数值初始化时。
3) 寄存器变量(register型)
格式:register 类型名 变量名
说明:
(1) 由于寄存器变量存储在计算机的CPU中,所以使用寄存器变量要比使用内存变量的操作要快得多,即可以提高执行效率。
(2) 寄存器变量的类型仅限:int, char或指向int,char的指针。
(3) 寄存器变量仅适用局部变量或函数的形式参数。
(4)C规定寄存器变量的数目不能超过3个,多余的将按auto处理
【例8.6.2】观察使用寄存器变量作循环控制变量时程序执行时间的变化。
#include "stdio.h "
#include "time.h "
unsigned int a,delay;
void main(void)
{
register unsigned int b;
long t;
t=time('\0' );
for(delay=0;delay<1000;delay++)
for(a=0;a<64000;a++)
printf("\n Time_escaping for NON-register loop:%ld ",time('\0')-t);
t=time('\0' );
for(delay=0;delay<1000;delay++)
for(b=0;b<64000;b++)
printf("\n Time_escaping for register loop:%ld ",time('\0')-t);
return ;
}
请大家自己运行下该程序,如果本程序在档次较低的旧机器上运行结果会非常明显,即两次结果差别很大
说明:对现在的计算机来说,这种类型的变量基本上和自动类型变量一样了,而且计算机内存管理中,由于寄存器资源十分宝贵,计算机系统也不完全按用户程序定义的这种类型变量来指定类型了。
3 全局变量的存储类型
1) 外部变量(extern型)
格式:extern 类型名变量名
这种变量我们在上一节例子中已经学习过。
在定义全局变量时,如果没有存储类型说明符,则认为它是隐含的extern型变量,系统在编译时为静态存储区的extern型全局变量分配内存单元。若一个变量使用了extern说明,则系统不再分配内存单元,而是从本程序中去查找同名的全局变量(即外部变量)。
C语言要求程序的全局变量只能在某个程序文件中说明一次。因此当希望在一个程序文件中使用另外文件中说明过的全局变量时,必须在该全局变量前用extern进行说明,这样在编译这些文件时,系统对程序中的extern说明的全局变量将不再分配存储单元,而只为无extern说明的全局变量分配存储单元,以便连接时供其他程序文件使用。
2) 静态全局变量(static型)
格式:static 类型名 变量名
静态全局变量和普通全局变量的区别在于:它只说明它的程序在本程序中有效,即虽然它是全局变量,但是其他程序文件中的程序并不知道它的存在,无法改变其内容,所以在静态局部变量仍不能满足编程要求时,可以通过建立独立的小程序文件模块,其中只使用必要的静态全局变量以及使用这些变量的函数,并独立编译这个程序文件后,再进行程序连接,就可以放心使用这个程序文件中的函数,而不必担心全局变量可能带来的不利影响。
【例8.6.1】选择一个整数随机数序列的“种子”,产生10 个随机数。
解题思路:
设计一个全局静态变量ran_num作为随机数序列的“种子”,其初值在主函数中输入。同时设计一个随机数产生函数random_num,其功能是产生一个随机整数,在主函数中循环调用10次函数random_num,并对得到的随机数进行整除1000,整除后的结果作为最后随机值。
#include "stdio.h "
static int ran_num;
void ran_num_seed(int seed);
int random_num(void);
void main( )
{
int a;
printf("\n Input Random number seed:");
scanf("%d",&ran_num);
for(a=0;a<10;a++)
{
if(a%5==0) printf("\n");
printf("%10d",random_num( )/1000);
}
printf("\n");
return ;
}
int random_num(void)
{
ran_num=ran_num*1023+2323;
return(ran_num);
}
下面以两个例子进行说明。
【例8.5.1】计算3、4、5、6、7的累加和,并分别显示累加结果。
解题思路:
设计一个全部变量sum,分别用来存放3、4的累加和,3、4、5的累加和,3、4、5、6的累加和,3、4、5、6、7的累加和,求和功能通过函数total来完成,在主函数中循环调用该函数,输出每步累加和的结果,循环变量初值和终值通过对全局变量a、b初始化进行设置。另外设计一个函数display_scope完成表头输出效果。
程序代码:
#include "stdio.h "
int sum; //全局变量
void display_scope(void);
int total(int x);
void display(void);
void main() //主函数
{
extern int a,b;
//由于外部变量a、b在后面定义,根据C语言规定,在前面使用必须要先说明
int count; //局部变量
sum=0;
display_scope();
for(count=a;count<=b;count++) //a,b已在本函数外被初始化为3和8
{ total(count);
printf(" Start from %d,End at %d: ",a,count);
display();
}
return ;
}
int a=3,b=8; //全局变量,其后均有效
void display_scope(void) //表头打印函数
{
int count; // 局部变量,本函数有效
for(count=1;count<=30;count++) printf(" -" );
printf(" \n The Scope ofSumation:From %d to %d:\n ",a,b);
for(count=1;count<=30;count++) printf(" -" );
printf("\n ");
}
int total(int x) //求累加结果
{
sum=sum+x; // sum为全局变量,所以本函数内外均有效
}
void display(void) // 显示累加结果
{
int a; //此处a为局部变量,本函数有效。由于与全局变量同名
//所以全局变量a在此无效
for(a=1;a<=5;a++) printf(" . ");
printf(" The current sum is %d\n ",sum);
}
运行结果:

在本例中,我们应该可以看到:
(1) 在一个函数中,如果全局变量与局部变量同名,则只有局部变量有效,即同名局部优先。
(2)如果一个函数使用的全局变量在该函数后说明,则应用extern进行外部变量说明,如果在其之前已说明,则无需进行附加说明

