第19讲 全局变量及其作用域和生存期 函数的存储分类
作用域与存储类型PPT课件

#include<> //不能省略 static int n; // 定义静态全局变量n void fn( ) { n=n+1; printf(“%d\n”,n); }
5.2 变量的存储类别
4、外部类型(extern) 定义格式: extern 类型 变量名;
在由多个源程序文件组成的程序中,如果一个文件要 使用另一个文件中定义的全局变量,这些源程序文件之间 通过外部类型的变量进行沟通。
注意: (1)#define、宏名和字符 串之间一定要有空格。 (2)宏名一般用大写字母表 示,以区别于普通标识符。 (3)宏被定义以后,一般不 能再重新定义。但可以用 #undef来终止宏定义。 (4)一个定义过的宏名可以 用来定义其他新的宏,但要 注意其中的括号。如:
#define A 20
#define B (A+10)
void main()
{
int a,b;
//a、b具有函数作用域
cout<<"输入两整数:"<<endl;
cin>>a>>b;
cout<<“a="<<a<<'\t'<<"b="<<b<<endl;
if(b>=a)
{
int t;
// t具有块作用域
t=a; a=b; b=t; //交换a,b的值
}
cout<<"a="<<a<<'\t'<<"b="<<b<<endl; // t已经无效
C语言中用户标示符的作用域和存储类

/* file2.c文件*/ #include <stdio.h> extern int n; void func () { printf ( "file2:%d\n", n); … }
所有函数都是外部的,因为不允许在函数内部定义另一个函数。但当定义函 数时,可以使用extern或static说明符。ຫໍສະໝຸດ 局部变量、全局变量和存储分类
用户标识符的作用域
局部变量及其作用域和生存期 全局变量及其作用域和生存期 函数的存储分类
用extern说明函数 用static说明函数
局部变量、全局变量和存储分类
auto变量、register变量、静态存储类的局部变量
float a; 就等价于: auto float a; auto变量的存储单元被分配在内存的动态存储区。每当进入函数体(或 复合语句)时,系统自动为auto变量分配存储单元;退出时自动释放这些 存储单元另作他用。 auto变量的作用域是从定义的位置起,到函数体(或复合语句)结束为止。
结果
** main(1) **:10 ** fun **:20 ** main(2) **:10 即全局变量sum的作用域是除 函数fun以外的整个程序;局部 变量sum的作用域仅是函数fun 内部。
全局变量是在函数外部任意位置上定义的变量,它的作用域是从变量定义 的位置开始,到整个源文件结束止。
全局变量可使用extern和static两种说明符。
全局变量是在函数外部任意位置上定义的变量,它的作用域是从变量定义 的位置开始,到整个源文件结束止。
例如
void fun1 ( void); void fun2 ( void ); int sum; /*定义全局变量*/ main () { … sum++; … } void fun1 ( void ) { … sum++; … } int test; /*定义全局变量*/ void fun2 ( void ) { … sum++; test =1; … } sum是在整个源程序的开始定义的,它的作 用域是整个程序。 test是在函数fun2前定义的,它的作用域从定 义处开始直到程序结束。 全局变量的使用相当于为函数之间的数据 传递另外开辟了一条通道。 全局变量的生存期是整个程序的运行期间。 若全局变量和某个函数中的局部变量同名, 则在该函数中,此全局变量被屏蔽,在该函数 内,访问的是局部变量,与同名的全局变量不 发生任何关系。
生存周期与作用域

3.静态存储方式
ห้องสมุดไป่ตู้
4.在一个项目里的各个源文件中都是有效的
静态全局变量:
1.需要用static声明
2.同全局变量,但在程序编辑阶段分配内存空间
3.静态存储方式
4.只在它声明的源文件中是有效的
static生命周期
静态变量的类型说明符是static。静态变量当然是属于静态存储方式,但是属于静态存储方式的量不一定就是静态变量,例如外部变量虽属于静态存储方式,但不一定是静态变量,必须由 static加以定义后才能成为静态外部变量,或称静态全局变量。对于自动变量,它属于动态存储方式。但是也可以用static定义它为静态自动变量,或称静态局部变量,从而成为静态存储方式。由此看来,一个变量可由static进行再说明,并改变其原有的存储方式。
2.静态全局变量
全局变量(外部变量)的说明之前再冠以static 就构成了静态的全局变量。全局变量本身就是静态存储方式,静态全局变量当然也是静态存储方式。这两者在存储方式上并无不同。这两者的区别虽在于非静态全局变量的作用域是整个源程序,当一个源程序由多个源文件组成时,非静态的全局变量在各个源文件中都是有效的。而静态全局变量则限制了其作用域,即只在定义该变量的源文件内有效,在同一源程序的其它源文件中不能使用它。由于静态全局变量的作用域局限于一个源文件内,只能为该源文件内的函数公用,因此可以避免在其它源文件中引起错误。
1. 静态局部变量
在局部变量的说明前再加上static说明符就构成静态局部变量。例如:
static int a,b; static float array[5]={1,2,3,4,5};
静态局部变量属于静态存储方式,它具有以下特点:
C语言中变量储存的类别

C语言中变量储存的类别C语言根据变量的生存周期来划分,可以划分为静态存储方式和动态存储方式。
静态存储方式:是指在程序的运行期间分配固定的存储空间的方式。
静态存储区中存储放了在整个程序执行过程中都存在的变量,如全局变量动态存储方式:是指在程序运行期间根据需要进行动态的分配存储空间的方式。
动态存储区中存放的变量是根据程序运行需要而进行的需要而建立和释放的。
通常包括:1.函数形式参数;2.自动变量;3.函数调用时的现场保护、4.和返回值地址等。
C语言中的存储类别又分为4类:自动(auto)、静态(static)、动态(extern)寄存器(register)1、用关键字auto定义的变量为自动变量,auto可以省略,auto 不写则隐含定为”自动存储类别“,属于动态存储方式。
2、用static修饰的为静态变量,如果定义在函数内部,称之为静态局部变量;如果定义在函数外部,称之为静态外部变量,注意:静态局部变量属于静态存储类别,在静态存储区内分配存储单元,在程序整个运行期间都不释放;静态局部变量在编译时赋初值,即只赋初值一次;如果在定义局部变量时,不赋初值的话,则对静态局部变量来说,编译时自动赋初值0.(对数值型变量)或空字符(对字符变量)。
3、为了提高效率,C语言允许将局部变量得值放在CPU中的寄存器中,这种变量叫”寄存器变量“,用关键字register做声明注意:只有局部自动变量和形式参数可以作为寄存器变量;一个计算机系统中的寄存器数目有限,不能定义任意多个寄存器变量局部静态变量不能定义为寄存器变量。
4、用extern声明的变量是外部变量,外部变量的意义是某函数可以调用在该函数之后定义的变量任务:运行结果是x=2;x=4;x=8;x=16;x=32;x=100。
变量的作用域和生存期

变量的作用域局部变量和全局变量在函数和复合语句内定义的变量,只在本函数或复合语句范围内有效(从定义点开始到函数或复合语句结束),他们称为内部变量或局部变量。
在函数之外定义的变量是外部变量,也称为全局变量(或全程变量)。
如果在一个函数中全局变量和局部变量同名,则在局部变量的作用范围内,外部变量被“屏蔽”,即他不起作用,此时局部变量是有效的。
全局变量的作用是增加函数间数据联系的渠道。
虽然全局变量有以上优点,但建议不必要时不要使用全局变量,因为全局变量在程序的全部执行过程中都占用存储单元,而不是仅在需要时才开辟单元。
在程序设计时,对模块的划分要求:内聚性强,与其他模块的耦合性弱,这样便于程序的移植,可读性强。
变量的生存期变量的存储方式分为两种:静态存储方式和动态存储方式。
静态存储方式是指在程序与性能期间由系统在静态存储区分配存储空间的方式,在程序运行器件不释放;而动态存储方式则是在函数调用期间根据需要在动态存储区分配存储空间的方式。
这就是变量的存储区别。
Auto----声明自动变量函数中的形参和在函数中定义的变量都属于此类。
在调用这些函数时,系统给这些变量分配存储空间,函数调用结束时就自动释放这些存储空间。
因为这类局部变量称为自动变量(auto 变量)。
关键字auto作为存储类别的声明。
Auto可省略Static-----声明静态变量希望函数中的变量的局部变量的值在函数调用结束后不消失而继续保留原值,即其占用的存储单元不释放,在下一次该函数调用时,该变量已有值,就是上一次函数调用结束时的值。
这时就用关键字static指定该局部变量为“静态存储变量”。
对静态局部变量的说明静态局部变量属于静态存储类别,在静态存储区内分配存储单元,在程序整个运行期间都不释放。
而自动变量(即动态局部变量)属于动态存储类别,占胴体啊存储区空间而不占静态存储区空间,函数调用结束后即释放。
对静态局部变量是在编译时赋初值的,即只赋初值一次,在以后每次调用函数时不再重新赋初值而只是保留上次函数调用结束时的值。
03-作用域与存储类别

f函数中的 自动局部
变量k
int main()
main函数 中的自动 局部变量k
{ int k=2; //auto int =2;
cout<<f(k)<<endl; cout<< f(k)<<endl; system("pause"); return 0;
}
问题一: f函数中的k和main函数中的k会冲突吗?
}
扩展i的 作用域
int i=5; int main() { int j=20;
cout<<j; fun(); system("pause"); return 0; }
全部变量示例
#include "iostream“ using namespace std; int m=10; void f1(int n)
全局变量m
形参n(局 部变量)
问题四: 程序的输出结果是什么?
{ n=2*n;m=m/3; } //m=3,n=4(形参n)
int n;
void f2()
全局变量n
开始执行分程序就生成,分程序执行结束就消亡 4 初始化:可以初始化,缺省值为随机值
自动局部变量示例
#include "iostream“
using namespace std;
int f(int x) { x++;
int k=5; k++;
形参也是 局部变量
//auto int k=5;
return x+k; }
作用域与存储类别
作用域与生存期的概念
➢作用域(可见性): 在什么范围内可以被访问
局部变量、全局变量、静态变量的含义及存储位置

局部变量、全局变量、静态变量的含义及存储位置1.局部变量在⼀个函数内部定义的变量是内部变量,它只在本函数范围内有效,也就是说只有在本函数内才能使⽤它们,在此函数以外时不能使⽤这些变量的,它们称为局部变量。
局部变量保存在动态数据区的栈中,只有在所在函数被调⽤时才动态地为变量分配存储单元。
1).主函数main中定义的变量也只在主函数中有效.2).不同函数中可以使⽤名字相同的变量,它们代表不同的对象,互不⼲扰.3).形参也是局部变量.4).在复合语句中定义的局部变量,这些变量只在本复合语句中有效.2.全局变量在函数外定义的变量是外部变量,外部变量是全局变量,全局变量可以为本⽂件中其它函数所共⽤,它的有效范围从定义变量的位置开始到本源⽂件结束。
全局变量位于静态数据区中。
1).设全局变量的作⽤:增加了函数间数据联系的渠道.2).建议不再必要的时候不要使⽤全局变量,因为a.全局变量在程序的全部执⾏过程中都占⽤存储单元.b.它使函数的通⽤性降低了3).如果外部变量在⽂件开头定义,则在整个⽂件范围内都可以使⽤该外部变量,如果不再⽂件开头定义,按上⾯规定作⽤范围只限于定义点到⽂件终了.如果在定义点之前的函数想引⽤该外部变量,则应该在该函数中⽤关键字extern作外部变量说明.4).如果在同⼀个源⽂件中,外部变量与局部变量同名,则在局部变量的作⽤范围内,外部变量不起作⽤.3.静态变量静态变量并不是说其就不能改变值,不能改变值的量叫常量。
其拥有的值是可变的,⽽且它会保持最新的值。
说其静态,是因为它不会随着函数的调⽤和退出⽽发⽣变化。
即static局部变量只被初始化⼀次,下⼀次依据上⼀次结果值;静态变量的作⽤范围要看静态变量的位置,如果在函数⾥,则作⽤范围就是这个函数。
静态变量属于静态存储⽅式,其存储空间为内存中的静态数据区(在静态存储区内分配存储单元),该区域中的数据在整个程序的运⾏期间⼀直占⽤这些存储空间(在程序整个运⾏期间都不释放),也可以认为是其内存地址不变,直到整个程序运⾏结束(相反,⽽auto⾃动变量,即动态局部变量,属于动态存储类别,占动态存储空间,函数调⽤结束后即释放)。
变量的生命周期和作用域

变量的生命周期和作用域在计算机编程中,变量是一个非常重要的概念。
它们用于存储和表示数据,使得程序能够进行各种计算和操作。
然而,变量并不是一直存在的,它们有自己的生命周期和作用域。
生命周期指的是变量从创建到销毁的整个过程。
在程序中,变量的生命周期由其声明和定义的位置决定。
一般来说,变量可以分为全局变量和局部变量。
全局变量是在整个程序中都可见和访问的变量。
它们通常在函数外部声明,并且在任何函数中都可以使用。
全局变量的生命周期从程序开始执行到结束。
这意味着,全局变量的值在程序的不同部分都是可用的,但也容易被误用或滥用。
因此,在使用全局变量时需要谨慎,避免不必要的副作用和混乱。
与全局变量相对应的是局部变量。
局部变量是在函数内部声明的变量,它们只在所属函数中可见和访问。
局部变量的生命周期仅限于其所属函数的执行过程。
一旦函数执行完毕,局部变量就会被销毁,其所占用的内存空间也会被释放。
这种限制使得局部变量更加安全和可控,避免了变量的冲突和混淆。
除了生命周期,变量还有作用域的概念。
作用域指的是变量在程序中有效的范围。
在大多数编程语言中,作用域可以分为全局作用域和局部作用域。
全局作用域意味着变量在整个程序中都可见和访问。
在全局作用域中声明的变量可以被程序中的任何函数使用。
这种作用域通常用于需要在多个函数中共享数据的情况。
然而,全局作用域也容易导致变量的滥用和混淆,因此需要谨慎使用。
与全局作用域相对应的是局部作用域。
局部作用域意味着变量只在其所属的函数或代码块中可见和访问。
在局部作用域中声明的变量只能在其所属的函数或代码块中使用,无法被其他函数或代码块访问。
这种作用域的好处是可以限制变量的可见性和访问范围,提高程序的安全性和可维护性。
在一些编程语言中,还存在着块级作用域的概念。
块级作用域是指由一对花括号({})括起来的代码块中声明的变量。
这些变量只在该代码块中有效,超出该代码块范围后就会被销毁。
块级作用域的引入使得变量的作用域更加灵活和可控。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
例8.4 编一函数求出10个整数的最大值、最小值和平均值。
main()
int max,min;
{int x[10],j;
float f(int a[10])
float average;
{ int i,sum=a[0];
for(j=0;j<10;j++)
float aver;
scanf("%d",&x[j]);
}
A) 34756
B) 23445
C) 35745
D) 12345
8.12 下面程序的输出结果是 。
fun3(int x)
{
static int a=3;
a+=x;
return(a);
}
main()
{
int k=2, m=1, n;
n=fun3(k);
n=fun3(m);
printf("%d\n",n);
2 内部函数 当定义一个函数时,若在函数返回值的类型前加上static时,
称此函数为“静态”函数(或“内部”函数)。它只能被本 编译单位中的其它函数所调用。
使用静态函数,可避免不同的编译单位因为函 数同名而引起的混乱。
例:外部函数
/* file1.c */ main() {extern float f(float a,float b);
/* 说明f是其它文件(编译单位)已经定义的外部函数 */
float x,y,z; …… z=f(x,y); …… }
/* file2.c */ extern float f(float a,float b) { …… }
static float f(float a,float b)
第八章 作业
教材P128 习题八 第一大题:1、2、3、5、7、8小题; 第二大题:1、2、3、4小题;
printf("%d",x);
}
printf("\n");
}
sub(int s[])
{ static int t=3;
int y;
y=s[t];
t--;
return y;
}
A) 1 2 3 4
B) 4 3 2 1
C) 0 0 0 0
D) 4 4 4 4
8.11 下面程序的输出结果是
。
#include <stdio.h>
}
A) 3
B) 0
C) 5
。 D) 4
下面程序的输出结果是 。 #include <stdio.h> #define MAX_COUNT 4 void fun(); main() { int count; for (count=1; count<=MAX_COUNT; count++) fun(); } void fun()
(2) 当一个程序由多个文件组成时,每个文件都是一个独立 的编译单位。如果多个文件中都需要用同一个全局变量,这时 若在每个文件中都定义一个同名的全局变量,则单独编译各个 文件时不会产生错误,编译程序将按定义分别为它们分配存储 空间;但当连接时,将产生同一变量的重复定义的错误。
解决办法是:在其中一个文件中定义的全局变量,在其它 文件中用extern进行说明,说明这些全局变量已在某一编译单 位中定义过,通知编译程序不必再为它们开辟存储单元,只是 将作用域进一步扩展到本编译单位中。
}
aver=sum/10.0;
return aver;
}
例8.5 全局变量与局部变量同名问题。
int sum;
运行结果为:
void fun(void);
**main(1)**:10
main()
** fun **:20
{
**main(2)**:10
sum=10;
printf("**main(1)**:%d\n",sum); 虽然全局变量的作用域大,
一文件的所有函数都能引用全局变量的值,如果在一个函 数中改变了某全局变量的值,就能影响使用该全局变量的 其它函数,相当于各个函数间有了直接传递的通道。 (2)全局变量的生存期是整个程序的运行期间,即“长期”。 (3)若全局变量与某一函数中的局部变量同名,则在该函数中, 全局变量被屏蔽,使用局部变量。
8.14 下列程序执行后输出的结果是
#include <stdio.h>
f(int a)
{ int b=0;
static c=3;
a=c++,b++;
return (a);
}
main( )
{
int a=2,i,k;
for(i=0;i<2;i++) k=f(a++);
printf("%d\n",k);
printf("** fun **:%d\n",sum);
3.人在读程序时,难以确
}
定某一时刻的当前值。
2. 全局变量作用域的扩展
(1) 当全局变量定义在后,引用它的函数在前时,应该在引 用它的函数中用extern对此全局变量进行说明,使其作用域从 extern说明处起,延伸到该函数末尾。也可将extern写在函数 之外,使其作用域延伸至文件末尾。
void fun( int s[])
{ static int j=0;
do
s[j]+=s[j+1];
while(++j<2);
}
main()
{ int k, a[10]={1,2,3,4,5};
for(k=1; k<3; k++) fun(a);
for(k=0; k<5; k++) printf("%d", a[k]);
main()
{
……
}
void gx() { …… }
扩展后 x,y的 作用域
int x,y;
void gy() { ……
x,y的 作用域
}
例:在不同文件中扩展全局变量的作用域
/*file1.c*/
int x,y;
main( )
{
……
扩
f1();
展
f2();
后
f3();
x,y的
x
……
作用域
的
}
作
f1( )
fun();
生存期长,用起来似乎方便
printf("**main(2)**:%d\n",sum); 灵活,但除十分必要外,一
}
般不提倡使用全局变量。主
void fun(void)
要有以下原因:
{
全局变量sum在fun
int sum; 函数中不起作用。
sum=20;
1.长期占用存储空间。 2.影响了函数的独立性, 不便于移植。
用
{ x=111;
域
……
}
/*file2.c*/ extern int x; f2( ) {
printf(“%d\n”,x); /*111*/ …… } f3( ) { x++; printf(“%d\n”,x); /*112*/
…… }
3.不允许扩展其作用域的全局变量(静态全局变量)
当定义全局变量时,若加上static,则称为静态全局变量, 其作用域仅限于本编译单位(本文件)。
/*file1.c*/ static int n; void f(); main() { …… f(); }
n的作 用域被 限定死
/*file2.c*/ extern int n; void f() {
…… }
注意:static对局部变量和全局变量的作用效果不同。对局 部变量:作用域没变,存储类改为静态;对全局变量:存储 类没变,作用域仅限于本文件(小全局)。
例:在同文件中扩展全局变量的作用域
main( )
{void gx(),gy();
extern int x,y;
…… gx(); gy();
……
扩展后 新增的 作用域
}
void gx( ) {……}
书印错!
int x,y;
void gy( ) { ……Fra bibliotekx,y的原 作用域
}
extern int x,y;
8.4 函数的存储分类
1 外部函数 当定义一个函数时,若在函数返回值的类型前加上extern(或
缺省)时,称此函数为“外部”函数。它可以被同一个程序的其 它文件中的函数调用。
当函数调用语句与被调函数不在同一编译单位(源文件),且函 数的返回值为非整型时,应该在调用语句所在函数的说明部分用 extern对所调用的函数进行说明。
{ static int i; i+=2; printf("%d",i);
}
以下程序的输出结果是 。 main() {
int a=3,b=2,c=1; c-=++b;
b*=a+c; {
int b=5,c=12; c/=b*2; a-=c; printf(“%d,%d,%d,”,a,b,c); a+=--c; } printf(“%d,%d,%d\n”,a,b,c); }
习题分析
8.9 以下程序的输出结果是
。
#include <stdio.h>
main()
{ int k=4,m=1,p;
p=func(k,m); printf("%d,",p);