多文件之间的函数调用
多文件之间也可以进行函数的相互调用,根据函数能否被其他源文件调用,可以将函数分为外部函数和内部函数,下面分别进行讲解。
1、 外部函数
在实际开发中,一个项目的所有代码不可能在一个源文件中实现,而是把项目拆分成多个模块,在不同的源文件中分别实现,最终再把它们整合在一起。为了减少重复代码,一个源文件有时需要调用其他源文件中定义的函数。在C语言中,可以被其他源文件调用的函数称为外部函数。
外部函数的定义方式是在函数的返回值类型前面添加extern关键字,表明该函数可以被其他的源文件调用。当有源文件要调用其他源文件中的外部函数时,需要在本文件中使用extern关键字声明要调用的外部函数,示例代码如下:
extern int add(int x,int y); //add()函数是定义在其他源文件中的外部函数
在上述示例代码中,编译器会通过extern关键字判知add()函数是定义在其他文件中的外部函数。
为了帮助大家理解外部函数的概念,下面通过一个案例演示外部函数地调用,该案例中有first.c与second.c两个源文件,first.c文件中定义了一个外部函数add(),second.c文件中需要调用add()函数,则first.c文件与second.c文件的代码分别如例1所示。
例1
first.c
1 extern int add(int x,int y) //定义外部函数add()
2 {
3 return x+y;
4 }
second.c
1 extern int add(int x,int y); //使用 extern 关键字声明要调用的外部函数add()
2 int main()
3 {
4 printf("%d",add(1,2)); //调用外部函数add()
5 return 0;
6 }
例1的运行结果如图1所示。
图1 例1运行结果
在例1中, first.c文件使用extern关键字定义了外部函数add(),表明add()函数可以被其他源文件调用。second.c文件中,第1行代码使用extern关键字声明add()函数;第4行代码调用add()函数,并传入参数1和2。由图1可知,成功输出结果3。
需要注意的是,在使用extern关键字声明外部函数时,函数的返回值类型、函数名与参数列表都需要与原函数保持一致。
上面讲解的内容是外部函数的标准定义与调用方式,但随着编译器地发展,编译器默认用户定义的函数都是外部函数,因此用户在定义函数时即使不写extern关键字,定义的函数也可以被其他源文件调用,调用外部函数的源文件也不必在本文件中使用extern关键字声明外部函数。例如例1中first.c文件中的代码可以简化如下:
int add(int x,int y) //编译器默认add()函数为外部函数
{
return x+y;
}
second.c文件中代码可以简化如下:
int main()
{
printf("%d",add(1,2)); //在 second.c 文件中可以直接调用 add()函数
return 0;
}
2、 内部函数
在C语言程序中,只要在当前文件中声明一个函数,该函数就能够被其他文件调用。但是当多人参与开发一个项目时,很有可能会出现函数重名的情况,这样,不同源文件中重名的函数就会互相干扰。此时,就需要一些特殊函数,这些函数只在它的定义文件中有效,不能被其他源文件调用,该类函数称为内部函数。
在定义内部函数时,需要在函数的返回值类型前面添加static关键字(又称为静态函数),被声明为静态函数后,函数只能在本文件中调用,内部函数定义示例代码如下:
static void show(int x) //添加static关键字定义内部函数
{
printf("%d",x);
}
为了让读者熟悉内部函数的作用,接下来通过一个案例演示内部函数的用法,该案例包含first.c、second.c和main.c三个文件,在first.c和second.c文件中都定义了一个show()函数,只是second.c文件将show()函数声明为了内部函数。在main.c文件中调用show()函数。first.c、second.c和main.c文件代码如例2所示。
例2
first.c
1 void show()
2 {
3 printf("%s \n","first.c" );
4 }
second.c
1 static void show() //show()函数为内部函数
2 {
3 printf("%s \n","second.c");
4 }
main.c
1 int main()
2 {
3 show(); //调用show()函数
4 return 0;
5 }
例2运行结果如图2所示。
图2 例2运行结果
在例2中,first.c文件与second.c文件中分别定义了show()函数,second.c文件中的show()函数被定义为了静态函数。在main.c文件中调用show()函数,从图2可以看出,first.c中的show()函数被调用成功了,而second.c文件中的show()函数未被调用,因此说明内部函数只在second.c文件中有效,无法在别的文件中调用。
脚下留心:多文件中的函数重名
在例2中,如果将second.c中修饰show()函数的关键字static删除,运行时程序会提示错误,如图3所示。
图3 程序提示错误
从图3中的错误结果可以看出,多个源文件中出现同名函数,在调用时会发生重定义错误。