1.4 内部函数和外部函数
前面讲解了变量的作用域,那么函数是否有作用域呢?回答是肯定的,函数同样也存在作用域。如果在一个源文件中定义的函数只能被该文件中的函数所调用,而不能被同一程序其他文件中的函数调用,那么我们称之为内部函数,其定义的一般形式为:
static函数类型函数名(参数表)
如果一个函数既可以被同一个源文件中的函数调用,又可以被同一程序其他文件中的函数调用,我们称之为外部函数。如果定义函数时没有加关键字static或者extern,那么这种函数也是外部函数。其定义的一般形式为:
extern函数类型函数名(参数表)
从上面的描述中可以看出,外部函数和内部函数之间的最大区别莫过于它们的作用范围不同,内部函数的作用范围是它所在的源文件,而外部函数的作用范围则不局限于它所在的源文件。接下来看看下面的代码,通过对下面的代码进行分析来加深对内部函数和外部函数的理解。
/*以下代码存放于file.h中*/
include<stdio.h>
typedef struct_stu
{
char name[10];
int score;
}stu;
/*以下代码存放于file1.cpp中*/
include"file.h"
static void input(stu student[],int n)
{
int i;
for(i=0;i<n;i++)
{
printf("请输入学生的姓名:");
scanf("%s",&student[i].name);
printf("请输入学生的总成绩:");
scanf("%d",&student[i].score);
}
return;
}
int main(void)
{
stu student[4];
extern void sort(stu student[],int n);
extern void bubble_sort(stu student[],int n);
extern void print(stu student[],int n);
input(student,4);
sort(student,4);
print(student,4);
bubble_sort(student,4);
print(student,4);
return 0;
}
/*以下代码存放于file2.cpp中*/
include"file.h"
extern void sort(stu student[],int n)
{
int i,j,k;
stu temp;
for(i=0;i<n-1;i++)
{
k=i;
for(j=i+1;j<n;j++)
{
if(student[j].score<student[k].score)
k=j;
}
if(k!=i)
{
temp=student[i];
student[i]=student[k];
student[k]=temp;
}
}
printf("使用选择法升序排列的结果为:\n");
return;
}
/*以下代码存放于file3.cpp中*/
include"file.h"
void bubble_sort(stu student[],int n)
{
int i,j,flag;
stu temp;
for(i=0;i<n-1;i++)
{
flag=1;
for(j=0;j<n-i-1;j++)
{
if(student[j].score<student[j+1].score)
{
temp=student[j];
student[j]=student[j+1];
student[j+1]=temp;
flag=0;
}
}
if(1==flag)
break;
}
printf("使用冒泡法降序排列的结果为:\n");
return;
}
/*以下代码存放于file4.cpp中*/
include"file.h"
void print(stu student[],int n)
{
int j;
for(j=0;j<n;j++)
{
printf("学生%s的总成绩为:%d\n",student[j].name,student[j].score);
}
return;
}
总共有5个文件:1个头文件file.h,4个源文件file1.cpp、file2.cpp、file3.cpp和file4.cpp。看看运行结果:
请输入学生的姓名:小王
请输入学生的总成绩:32
请输入学生的姓名:小李
请输入学生的总成绩:56
请输入学生的姓名:小刚
请输入学生的总成绩:34
请输入学生的姓名:小张
请输入学生的总成绩:43
使用选择法升序排列的结果为:
学生小王的总成绩为:32
学生小刚的总成绩为:34
学生小张的总成绩为:43
学生小李的总成绩为:56
使用冒泡法降序排列的结果为:
学生小李的总成绩为:56
学生小张的总成绩为:43
学生小刚的总成绩为:34
学生小王的总成绩为:32
分析上面的代码,由于每个源文件都用到了定义的结构体,所以在此把结构体放到一个头文件中去。在上面的代码中,使用static定义了一个内部函数“static void input(stu student[],int n)”,其功能是输入学生的相关信息;使用extern关键字定义了一个外部函数“extern void sort(stu student[],int n)”,其功能是选择法升序排序;不使用任何关键字定义了一个外部函数“void bubble_sort(stu student[],int n)”,其功能为冒泡法降序排序。同时,因为对两种排序方式的结果都进行了打印,所以在file4.cpp文件中编写了一个外部函数“void print(stu student[],int n)”,然后在main()函数中对进行了排序的结果调用print()函数进行打印。读者在使用VC++6.0进行编译的过程中需要在建立的工程中添加上面4个源文件和1个头文件。
我们发现,使用内部函数的优点是:不同的人编写不同的函数时,不用担心自己定义的函数是否会与其他文件中的函数同名,因为作用域的关系,同名也不会产生影响。所以,在编程的过程中,对于那些只需要在一个源文件中使用的函数,我们要养成加上static的习惯。当然,对于那些不仅仅在一个源文件中使用的函数,我们需要将其定义为外部函数。
对于内部函数和外部函数的讲解到这里就结束了,相信读者应该掌握了内部函数和外部函数的使用。