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的习惯。当然,对于那些不仅仅在一个源文件中使用的函数,我们需要将其定义为外部函数。

对于内部函数和外部函数的讲解到这里就结束了,相信读者应该掌握了内部函数和外部函数的使用。