Board logo

标题: C基础教程 第八章 函 数(下) [打印本页]

作者: 苹果也疯狂    时间: 2011-10-21 12:14     标题: C基础教程 第八章 函 数(下)

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
/*外部变量xlxwxh的定义*/


[程序演示]

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)设置项目名称

打开菜单,选取ProjectProject name,输入项目文件名即可。

4)编译、连接,运行,查看结果

与单个源文件相同。编译产生的目标文件,以及连接产生的可执行文件,它们的主文件名,均与项目文件的主文件名相同。

注意:当前项目文件调试完毕后,应选取ProjectClear project,将其项目名称从“Projectname”中清除(清除后为空)。否则,编译、连接和运行的,始终是该项目文件!

5)关于错误跟踪

缺省时,仅跟踪当前一个源程序文件。如果希望自动跟踪项目中的所有源文件,则应将OptionsEnvironmentMessage 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'(字符型);且每次调用它们所在的函数时,不再重新赋初值,只是保留上次调用结束时的值!

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)对寄存器变量的实际处理,随系统而异。例如,微机上的MSCTC 将寄存器变量实际当作自动变量处理。

3)允许使用的寄存器数目是有限的,不能定义任意多个寄存器变量。

7.6.2
外部变量的存储方式

外部变量属于静态存储方式:


1)静态外部变量──只允许被本源文件中的函数引用

其定义格式为:
static
数据类型
外部变量表;

2)非静态外部变量──允许被其它源文件中的函数引用

定义时缺省static关键字的外部变量,即为非静态外部变量。其它源文件中的函数,引用非静态外部变量时,需要在引用函数所在的源文件中进行说明:

extern
数据类型
外部变量表;

注意:在函数内的extern变量说明,表示引用本源文件中的外部变量!而函数外(通常在文件开头)的extern变量说明,表示引用其它文件中的外部变量。


静态局部变量和静态外部变量同属静态存储方式,但两者区别较大:

1)定义的位置不同。静态局部变量在函数内定义,静态外部变量在函数外定义。

2)作用域不同。静态局部变量属于内部变量,其作用域仅限于定义它的函数内;虽然生存期为整个源程序,但其它函数是不能使用它的。

静态外部变量在函数外定义,其作用域为定义它的源文件内;生存期为整个源程序,但其它源文件中的函数也是不能使用它的。


3)初始化处理不同。静态局部变量,仅在第1次调用它所在的函数时被初始化,当再次调用定义它的函数时,不再初始化,而是保留上1次调用结束时的值。而静态外部变量是在函数外定义的,不存在静态内部变量的“重复”初始化问题,其当前值由最近1次给它赋值的操作决定。

务必牢记:把局部变量改变为静态内部变量后,改变了它的存储方式,即改变了它的生存期。把外部变量改变为静态外部变量后,改变了它的作用域,限制了它的使用范围。因此,关键字“static”在不同的地方所起的作用是不同的。




欢迎光临 电子技术论坛_中国专业的电子工程师学习交流社区-中电网技术论坛 (http://bbs.eccn.com/) Powered by Discuz! 7.0.0