7.4 内部变量与外部变量
C语言中所有的变量都有自己的作用域。变量说明的位置不同,其作用域也不同,据此将C语言中的变量分为内部变量和外部变量。
7.4.1 内部变量
7.4.2 外部变量
7.4.1 内部变量
在一个函数内部说明的变量是内部变量,它只在该函数范围内有效。
也就是说,只有在包含变量说明的函数内部,才能使用被说明的变量,在此函数之外就不能使用这些变量了。所以内部变量也称“局部变量”。
例如:
int f1(int a) /*函数f1*/
{ int b,c;
……
} /*a,b,c作用域:仅限于函数f1()中*/
int f2(int x) /*函数f2*/
{ int y,z;
……
} /*x,y,z作用域:仅限于函数f2()中*/
main()
{ int m,n;
……
} /*m,n作用域:仅限于函数main()中*/
关于局部变量的作用域还要说明以下几点:
1.主函数main()中定义的内部变量,也只能在主函数中使用,其它函数不能使用。同时,主函数中也不能使用其它函数中定义的内部变量。因为主函数也是一个函数,与其它函数是平行关系。这一点是与其它语言不同的,应予以注意。
2.形参变量也是内部变量,属于被调用函数;实参变量,则是调用函数的内部变量。
3.允许在不同的函数中使用相同的变量名,它们代表不同的对象,分配不同的单元,互不干扰,也不会发生混淆。
4.在复合语句中也可定义变量,其作用域只在复合语句范围内。
7.4.2 外部变量
在函数外部定义的变量称为外部变量。以此类推,在函数外部定义的数组就称为外部数组。
外部变量不属于任何一个函数,其作用域是:从外部变量的定义位置开始,到本文件结束为止。
外部变量可被作用域内的所有函数直接引用,所以外部变量又称全局变量。
[案例7.9] 输入长方体的长(l)、宽(w)、高(h),求长方体体积及正、侧、顶三个面的面积。
/*案例代码文件名:AL7_9.C*/
/*功能:利用全局变量计算长方体的体积及三个面的面积*/
int s1,s2,s3;
int vs(int a,int b,int c)
{ int v;
v=a*b*c; s1=a*b; s2=b*c; s3=a*c;
return v;
}
main()
{int v,l,w,h;
clrscr();
printf("\ninput length,width and height: ");
scanf("%d%d%d",&l,&w,&h);
v=vs(l,w,h);
printf("v=%d s1=%d s2=%d s3=%d\n",v,s1,s2,s3);
getch();
} [程序演示]
对于全局变量还有以下几点说明:
(1)外部变量可加强函数模块之间的数据联系,但又使这些函数依赖这些外部变量,因而使得这些函数的独立性降低。
从模块化程序设计的观点来看这是不利的,因此不是非用不可时,不要使用外部变量。
(2)在同一源文件中,允许外部变量和内部变量同名。在内部变量的作用域内,外部变量将被屏蔽而不起作用。
(3)外部变量的作用域是从定义点到本文件结束。如果定义点之前的函数需要引用这些外部变量时,需要在函数内对被引用的外部变量进行说明。外部变量说明的一般形式为:
extern 数据类型 外部变量[,外部变量2……];
注意:外部变量的定义和外部变量的说明是两回事。外部变量的定义,必须在所有的函数之外,且只能定义一次。而外部变量的说明,出现在要使用该外部变量的函数内,而且可以出现多次。
[案例7.10] 外部变量的定义与说明。
/*案例代码文件名:AL7_10.C*/
int vs(int xl,int xw)
{ extern int xh; /*外部变量xh的说明*/
int v;
v=xl*xw*xh; /*直接使用外部变量xh的值*/
return v;
}
main()
{ extern int xw,xh; /*外部变量的说明*/
int xl=5; /*内部变量的定义*/
printf("xl=%d,xw=%d,xh=%d\nv=%d",xl,xw,xh,vs(xl,xw));
}
int xl=3,xw=4,xh=5; /*外部变量xl、xw、xh的定义*/
[程序演示]
7.5 内部函数和外部函数
当一个源程序由多个源文件组成时,C语言根据函数能否被其它源文件中的函数调用,将函数分为内部函数和外部函数。
7.5.1 内部函数(又称静态函数)
7.5.2 外部函数
7.5.3 多个源程序文件的编译和连接
7.5.1 内部函数(又称静态函数)
如果在一个源文件中定义的函数,只能被本文件中的函数调用,而不能被同一程序其它文件中的函数调用,这种函数称为内部函数。
定义一个内部函数,只需在函数类型前再加一个“static”关键字即可,如下所示:
static 函数类型 函数名(函数参数表)
{……}
关键字“static”,译成中文就是“静态的”,所以内部函数又称静态函数。但此处“static”的含义不是指存储方式,而是指对函数的作用域仅局限于本文件。
使用内部函数的好处是:不同的人编写不同的函数时,不用担心自己定义的函数,是否会与其它文件中的函数同名,因为同名也没有关系。
7.5.2 外部函数
外部函数的定义:在定义函数时,如果没有加关键字“static”,或冠以关键字“extern”,表示此函数是外部函数:
[extern] 函数类型 函数名(函数参数表)
{……}
调用外部函数时,需要对其进行说明:
[extern] 函数类型 函数名(参数类型表)[,函数名2(参数类型表2)……];
[案例7.11] 外部函数应用。
(1)文件mainf.c
main()
{ extern void input(…),process(…),output(…);
input(…); process(…); output(…);
}
(2)文件subf1.c
……
extern void input(……) /*定义外部函数*/
{……}
(3)文件subf2.c
……
extern void process(……) /*定义外部函数*/
{……}
(4)文件subf3.c
……
extern void output(……) /*定义外部函数*/
{……}
7.5.3 多个源程序文件的编译和连接
(1)一般过程
编辑各源文件 → 创建Project(项目)文件 → 设置项目名称 → 编译、连接,运行,查看结果。
(2)创建Project(项目)文件
用编辑源文件相同的方法,创建一个扩展名为.PRJ的项目文件:该文件中仅包括将被编译、连接的各源文件名,一行一个,其扩展名.C可以缺省;文件名的顺序,仅影响编译的顺序,与运行无关。
注意:如果有某个(些)源文件不在当前目录下,则应在文件名前冠以路径。
(3)设置项目名称
打开菜单,选取Project/Project name,输入项目文件名即可。
(4)编译、连接,运行,查看结果
与单个源文件相同。编译产生的目标文件,以及连接产生的可执行文件,它们的主文件名,均与项目文件的主文件名相同。
注意:当前项目文件调试完毕后,应选取Project/Clear project,将其项目名称从“Project name”中清除(清除后为空)。否则,编译、连接和运行的,始终是该项目文件!
(5)关于错误跟踪
缺省时,仅跟踪当前一个源程序文件。如果希望自动跟踪项目中的所有源文件,则应将Options/Environment/Message Tracking开关置为“All files ”:连续按回车键,直至“All files”出现为止。此时,滚动消息窗口中的错误信息时,系统会自动加载相应的源文件到编辑窗口中。
也可关闭跟踪(将“Message Tracking”置为“Off”)。此时,只要定位于感兴趣的错误信息上,然后回车,系统也会自动将相应源文件加载到编辑窗口中。
7.6 变量的动态存储与静态存储简介
在C语言中,对变量的存储类型说明有以下四种:自动变量(auto)、寄存器变量(register)、外部变量(extern)、静态变量(static)。自动变量和寄存器变量属于动态存储方式,外部变量和静态内部变量属于静态存储方式。
7.6.1 内部变量的存储方式
7.6.2 外部变量的存储方式
7.6.1 内部变量的存储方式
1.静态存储──静态内部变量
(1)定义格式: static 数据类型 内部变量表;
(2)存储特点
1)静态内部变量属于静态存储。在程序执行过程中,即使所在函数调用结束也不释放。换句话说,在程序执行期间,静态内部变量始终存在,但其它函数是不能引用它们的。
2)定义但不初始化,则自动赋以"0"(整型和实型)或'\0'(字符型);且每次调用它们所在的函数时,不再重新赋初值,只是保留上次调用结束时的值!
(3)何时使用静态内部变量
1)需要保留函数上一次调用结束时的值。
2)变量只被引用而不改变其值。
2.动态存储──自动局部变量(又称自动变量)
(1)定义格式:[auto] 数据类型 变量表;
(2)存储特点
1)自动变量属于动态存储方式。在函数中定义的自动变量,只在该函数内有效;函数被调用时分配存储空间,调用结束就释放。
在复合语句中定义的自动变量,只在该复合语句中有效;退出复合语句后,也不能再使用,否则将引起错误。
2)定义而不初始化,则其值是不确定的。如果初始化,则赋初值操作是在调用时进行的,且每次调用都要重新赋一次初值。
3)由于自动变量的作用域和生存期,都局限于定义它的个体内(函数或复合语句),因此不同的个体中允许使用同名的变量而不会混淆。即使在函数内定义的自动变量,也可与该函数内部的复合语句中定义的自动变量同名。
建议:系统不会混淆,并不意味着人也不会混淆,所以尽量少用同名自动变量!
[案例7.13]自动变量与静态局部变量的存储特性。
/*案例代码文件名:AL7_13.C*/
void auto_static(void)
{ int var_auto=0; /*自动变量:每次调用都重新初始化*/
static int var_static=0; /*静态局部变量:只初始化1次*/
printf(“var_auto=%d, var_static=%d\n”, var_auto, var_static);
++var_auto;
++var_static;
}
main()
{ int i;
for(i=0; i<5; i++) auto_static();
} [程序演示]
3.寄存器存储──寄存器变量
一般情况下,变量的值都是存储在内存中的。为提高执行效率,C语言允许将局部变量的值存放到寄存器中,这种变量就称为寄存器变量。定义格式如下:
register 数据类型 变量表;
(1)只有局部变量才能定义成寄存器变量,即全局变量不行。
(2)对寄存器变量的实际处理,随系统而异。例如,微机上的MSC和TC 将寄存器变量实际当作自动变量处理。
(3)允许使用的寄存器数目是有限的,不能定义任意多个寄存器变量。
7.6.2 外部变量的存储方式
外部变量属于静态存储方式:
(1)静态外部变量──只允许被本源文件中的函数引用
其定义格式为: static 数据类型 外部变量表;
(2)非静态外部变量──允许被其它源文件中的函数引用
定义时缺省static关键字的外部变量,即为非静态外部变量。其它源文件中的函数,引用非静态外部变量时,需要在引用函数所在的源文件中进行说明:
extern 数据类型 外部变量表;
注意:在函数内的extern变量说明,表示引用本源文件中的外部变量!而函数外(通常在文件开头)的extern变量说明,表示引用其它文件中的外部变量。
静态局部变量和静态外部变量同属静态存储方式,但两者区别较大:
(1)定义的位置不同。静态局部变量在函数内定义,静态外部变量在函数外定义。
(2)作用域不同。静态局部变量属于内部变量,其作用域仅限于定义它的函数内;虽然生存期为整个源程序,但其它函数是不能使用它的。
静态外部变量在函数外定义,其作用域为定义它的源文件内;生存期为整个源程序,但其它源文件中的函数也是不能使用它的。
(3)初始化处理不同。静态局部变量,仅在第1次调用它所在的函数时被初始化,当再次调用定义它的函数时,不再初始化,而是保留上1次调用结束时的值。而静态外部变量是在函数外定义的,不存在静态内部变量的“重复”初始化问题,其当前值由最近1次给它赋值的操作决定。
务必牢记:把局部变量改变为静态内部变量后,改变了它的存储方式,即改变了它的生存期。把外部变量改变为静态外部变量后,改变了它的作用域,限制了它的使用范围。因此,关键字“static”在不同的地方所起的作用是不同的。
from: http://other.mblogger.cn/posaidong/archive/07192005.aspx