8.10 内部函数与外部函数
函数本质上是全局的,但可以限定函数能否被别的文件所引用。
当一个源程序由多个源文件组成时,C语言根据函数能否被其它源文件中的函数调用,将函数分为内部函数和外部函数。
8.10.1 内部函数
如果在一个源文件中定义的函数,只能被本文件中的函数调用,而不能被同一程序其它文件中的函数调用,这种函数称为内部函数。
定义一个内部函数,只需在函数类型前再加一个“static”关键字即可,如下所示:
static 函数类型函数名(函数参数表)
{……}
关键字“static”,译成中文就是“静态的”,所以内部函数又称静态函数。
但此处“static”的含义不是指存储方式,而是指对函数的作用域仅局限于本文件。
使用内部函数的好处是:不同的人编写不同的函数时,不用担心自己定义的函数,是否会与其它文件中的函数同名,因为同名也没有关系。
8.10.2 外部函数
外部函数的定义:在定义函数时,如果没有加关键字“static”,或冠以关键字“extern”,表示此函数是外部函数:
[extern] 函数类型函数名(函数参数表)
{……}
调用外部函数时,需要对其进行说明:
[extern] 函数类型函数名(参数类型表)[,函数名2(参数类型表2)……];
例8.22 外部函数应用。
(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(……)/*定义外部函数*/
{……}
例8.23 数组排序----简单选择排序
file1.c
main()
{
extern void sort(int array[ ],int n);
int a[10],i;
for(i=0;i<10;i++)
scanf("%d",&a[i]);
sort(a,10);
for(i=0;i<10;i++)
printf("%d ",a[i]);
printf("\n");
}
file2.c
void sort(int array[],int n)
{ int i,j,k,t;
for(i=0;i<n-1;i++)
{ k=i;
for(j=i+1;j<n;j++)
if(array[j]<array[k]) k=j;
if(k!=i)
{ t=array[i];
array[i]=array[k];
array[k]=t;
}
}
}
8.11 多个源程序文件的编译和连接
(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”)。
此时,只要定位于感兴趣的错误信息上,然后回车,系统也会自动将相应源文件加载到编辑窗口中。
良好的源程序书写风格──注释
必要的注释,可有效地提高程序的可读性,从而提高程序的可维护性。
在C语言源程序中,注释可分为三种情况:
(1)在函数体内对语句的注释;
(2)在函数之前对函数的注释;
(3)在源程序文件开始处,对整个程序的总体说明。
函数体内的语句,是由顺序结构、选择结构和循环结构等三种基本结构构成的。
在什么地方加以注释的原则是:如果不加注释,理解起来就会有困难,或者虽无困难、但浪费时间。
(1)顺序结构
在每个顺序程序段(由若干条语句构成)之前,用注释说明其功能。
除很复杂的处理外,一般没有必要每条语句都加以注释。
(2)选择结构
在C语言中,选择结构是由if语句和switch语句来实现的。
一般地说,要在前面说明其作用,在每个分支条件语句行的后面,说明该分支的含义,如下所示:
1)if语句
/*……(说明功能)*/
if(条件表达式) /*条件成立时的含义*/
{……}
else /*入口条件含义*/
{……}
2)switch语句
/*……(说明功能)*/
switch(表达式)
{ case 常量表达式1:/*该入口值的含义*/
语句组;
……
case 常量表达式n:/*该入口值的含义*/
语句组;
default:/*该入口值的含义*/
语句组;
}
如果条件成立时(或入口值)的含义,已经很明确了,也可不再加以注释。
小结
1 函数概念:具有一定功能一定形式的程序单位。
2 一般将输入和输出放在main()函数中,程序主体另外定义为函数
3 函数定义与函数原型
4 值传递和址传递
5 参数传递和“哑实结合”,一一对应
6 函数返回值及类型
7 递归调用的特点
9 数组做实参与址传递
10 全局变量
11 静态变量与初始化
12 内部函数和外部函数。