详细了解一下static和extern吧

博客涉及C语言和存储方面的信息技术内容,但具体信息缺失。推测可能围绕C语言在存储操作、存储管理等方面展开。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

详细了解一下static和extern吧
清风客V等待 发表于 2005-10-19 11:49:00

C语言教程:第五章:函数(9)
加入时间:2005-10-7 来源:学生大 类别:计算机等级考试
 
  二、外部变量外部变量的类型说明符为extern。   

在前面介绍全局变量时已介绍过外部变量。这里再补充说明外部变量的几个特点:   
1. 外部变量和全局变量是对同一类变量的两种不同角度的提法。全局变是是从它的作用域提出的,外部变量从它的存储方式提出的,表示了它的生存期。   

2. 当一个源程序由若干个源文件组成时, 在一个源文件中定义的外部变量在其它的源文件中也有效。例如有一个源程序由源文件F1.C和F2.C组成: F1.C   
int a,b; /*外部变量定义*/   
char c; /*外部变量定义*/   
main()   
{    
……   
}   
F2.C   
extern int a,b; /*外部变量说明*/   
extern char c; /*外部变量说明*/   
func (int x,y)   
{   
……   
}   
在F1.C和F2.C两个文件中都要使用a,b,c三个变量。在F1.C文件中把a,b,c都定义为外部变量。在F2.C文件中用extern把三个变量说明为外部变量,表示这些变量已在其它文件中定义,并把这些变量的类型和变量名,编译系统不再为它们分配内存空间。 对构造类型的外部变量, 如数组等可以在说明时作初始化赋值,若不赋初值,则系统自动定义它们的初值为0。   

三、静态变量   

  静态变量的类型说明符是static。 静态变量当然是属于静态存储方式,但是属于静态存储方式的量不一定就是静态变量, 例如外部变量虽属于静态存储方式,但不一定是静态变量,必须由 static加以定义后才能成为静态外部变量,或称静态全局变量。 对于自动变量,前面已经介绍它属于动态存储方式。 但是也可以用static定义它为静态自动变量,或称静态局部变量,从而成为静态存储方式。   
由此看来, 一个变量可由static进行再说明,并改变其原有的存储方式。   

1. 静态局部变量   
  在局部变量的说明前再加上static说明符就构成静态局部变量。   
例如:   
static int a,b;   
static float array[5]={1,2,3,4,5};   
     
  静态局部变量属于静态存储方式,它具有以下特点:   
(1)静态局部变量在函数内定义,但不象自动变量那样,当调用时就存在,退出函数时就消失。静态局部变量始终存在着,也就是说它的生存期为整个源程序。   

(2)静态局部变量的生存期虽然为整个源程序,但是其作用域仍与自动变量相同,即只能在定义该变量的函数内使用该变量。退出该函数后, 尽管该变量还继续存在,但不能使用它。   

(3)允许对构造类静态局部量赋初值。在数组一章中,介绍数组初始化时已作过说明。若未赋以初值,则由系统自动赋以0值。   

(4)对基本类型的静态局部变量若在说明时未赋以初值,则系统自动赋予0值。而对自动变量不赋初值,则其值是不定的。 根据静态局部变量的特点, 可以看出它是一种生存期为整个源程序的量。虽然离开定义它的函数后不能使用,但如再次调用定义它的函数时,它又可继续使用, 而且保存了前次被调用后留下的值。 因此,当多次调用一个函数且要求在调用之间保留某些变量的值时,可考虑采用静态局部变量。虽然用全局变量也可以达到上述目的,但全局变量有时会造成意外的副作用,因此仍以采用局部静态变量为宜。   
[例5.15]main()   
{   
int i;   
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;   
void f();   
for (i=1;i<=5;i++)   
f();   
}   
void f()   
{   
static int j=0;   
++j;   
printf("%d/n",j);   
}   
void f()   
{   
static int j=0;   
++j;   
printf("%d/n",j);   
}   
由于j为静态变量,能在每次调用后保留其值并在下一次调用时继续使用,所以输出值成为累加的结果。读者可自行分析其执行过程。   

2.静态全局变量   
  全局变量(外部变量)的说明之前再冠以static 就构成了静态的全局变量。全局变量本身就是静态存储方式, 静态全局变量当然也是静态存储方式。 这两者在存储方式上并无不同。这两者的区别虽在于非静态全局变量的作用域是整个源程序, 当一个源程序由多个源文件组成时,非静态的全局变量在各个源文件中都是有效的。 而静态全局变量则限制了其作用域, 即只在定义该变量的源文件内有效, 在同一源程序的其它源文件中不能使用它。由于静态全局变量的作用域局限于一个源文件内,只能为该源文件内的函数公用, 因此可以避免在其它源文件中引起错误。从以上分析可以看出, 把局部变量改变为静态变量后是改变了它的存储方式即改变了它的生存期。把全局变量改变为静态变量后是改变了它的作用域, 限制了它   
的使用范围。因此static 这个说明符在不同的地方所起的作用是不同的。应予以注意。   

四、寄存器变量   

  上述各类变量都存放在存储器内, 因此当对一个变量频繁读写时,必须要反复访问内存储器,从而花费大量的存取时间。 为此,C语言提供了另一种变量,即寄存器变量。这种变量存放在CPU的寄存器中,使用时,不需要访问内存,而直接从寄存器中读写, 这样可提高效率。寄存器变量的说明符是register。 对于循环次数较多的循环控制变量及循环体内反复使用的变量均可定义为寄存器变量。   
[例5.16]求∑200i=1imain()   
{   
register i,s=0;   
for(i=1;i<=200;i++)   
s=s+i;   
printf("s=%d/n",s);   
}   
本程序循环200次,i和s都将频繁使用,因此可定义为寄存器变量。   
对寄存器变量还要说明以下几点:   

1. 只有局部自动变量和形式参数才可以定义为寄存器变量。因为寄存器变量属于动态存储方式。凡需要采用静态存储方式的量不能定义为寄存器变量。   

2. 在Turbo C,MS C等微机上使用的C语言中, 实际上是把寄存器变量当成自动变量处理的。因此速度并不能提高。&nbsp;而在程序中允许使用寄存器变量只是为了与标准C保持一致。3. 即使能真正使用寄存器变量的机器,由于CPU 中寄存器的个数是有限的,因此使用寄存器变量的个数也是有限的。   

内部函数和外部函数   

  函数一旦定义后就可被其它函数调用。 但当一个源程序由多个源文件组成时, 在一个源文件中定义的函数能否被其它源文件中的函数调用呢?为此,C语言又把函数分为两类:   

一、内部函数   

  如果在一个源文件中定义的函数只能被本文件中的函数调用,而不能被同一源程序其它文件中的函数调用, 这种函数称为内部函    
数。定义内部函数的一般形式是: static 类型说明符 函数名(形参表) 例如:   
static int f(int a,int b) 内部函数也称为静态函数。但此处静态static 的含义已不是指存储方式,而是指对函数的调用范围只局限于本文件。 因此在不同的源文件中定义同名的静态函数不会引起混淆。   

二、外部函数   
  外部函数在整个源程序中都有效,其定义的一般形式为: extern 类型说明符 函数名(形参表) 例如:   
extern int f(int a,int b)如在函数定义中没有说明extern或static则隐含为extern。在一个源文件的函数中调用其它源文件中定义的外部函数时,应 用extern说明被调函数为外部函数。例如:   
F1.C (源文件一)   
main()   
{   
extern int f1(int i); /*外部函数说明,表示f1函   
数在其它源文件中*/   
……   
}   
F2.C (源文件二)   
extern int f1(int i); /*外部函数定义*/   
{   
……   
}   

本章小结   

1. 函数的分类   
(1)库函数:由C系统提供的函数;   
(2)用户定义函数:由用户自己定义的函数;   
(3)有返回值的函数向调用者返回函数值,应说明函数类型( 即返回值的类型 );   
(4)无返回值的函数:不返回函数值,说明为空(void)类型;   
(5)有参函数:主调函数向被调函数传送数据;   
(6)无参函数:主调函数与被调函数间无数据传送;   
(7)内部函数:只能在本源文件中使用的函数;   
(8)外部函数:可在整个源程序中使用的函数。   

2. 函数定义的一般形式    
[extern/static] 类型说明符 函数名([形参表]) 方括号内为可选项。   

3. 函数说明的一般形式 [extern] 类型说明符 函数名([形参表]);    

4. 函数调用的一般形式 函数名([实参表])    

5. 函数的参数分为形参和实参两种,形参出现在函数定义中,实参出现在函数调用中,发生函数调用时,将把实参的值传送给形参。   

6. 函数的值是指函数的返回值,它是在函数中由return语句返回的。   

7. 数组名作为函数参数时不进行值传送而进行地址传送。形参和实参实际上为同一数组的两个名称。因此形参数组的值发生变化,实参数组的值当然也变化。   
<br>8. C语言中,允许函数的嵌套调用和函数的递归调用。&nbsp;  

9. 可从三个方面对变量分类,即变量的数据类型,变量作用域和变量的存储类型。在第二章中主要介绍变量的数据类型,本章中介绍了变量的作用域和变量的存储类型。   

10.变量的作用域是指变量在程序中的有效范围, 分为局部变量和全局变量。   

11.变量的存储类型是指变量在内存中的存储方式,分为静态存储和动态存储,表示了变量的生存期。   

12.变量分类特性表存储方式存储类型说明符何处定义生存期作用域赋值前的值可赋初值类型动态存储自动变量 auto 寄存器变量 register 函数或复合语句内被调用时在定义它的函数或复合语句内不定基本类型int或char外部变量extern函数之外整个源程序整个源程序静态局部变量static 函数或复合语句内静态全局变量static 函数之外整个源程序在定义它的函数或复合语句内在定义它的源文件内0任何类型
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值