在C语言中一旦程序的功能复杂时,我们便会想到使用多个文件来写函数,即是在主函数(含有main()函数的.c文件)中调用别的文件的函数。而这里的函数调用方式可以用2种方式来完成。
方式1:使用#include“XXX.X”直接将别的文件的内容直接包含到主函数中。
方式2:使用extern 声明外部文件已经定义的函数。
这里就先把这两种方式的简单栗子举一个。
(下面的所有代码编辑和编译运行都是使用VS2010完成的。)
方式1 栗子:
//fun.h *注意:这里的文件名是.h文件
#include <stdio.h>
void fun2()
{
printf("This is fun2.\n");
}
//main.c
#include <stdio.h>
#include <stdlib.h>
//直接将fun.h的文件包含(即内容复制)到main.c文件中
#include "fun.h"
int main()
{
printf("This is main.\n");
fun2();
system("pause");
}
运行结果:
This is fun2.
This is main.
请按任意键继续…
方式2 栗子:
//fun.c *注意:这里的文件名是.c文件
#include <stdio.h>
void fun2()
{
printf("This is fun2.\n");
}
//main.c
#include <stdio.h>
#include <stdlib.h>
//外部函数的声明语句,extern 只是标记这个函数别的文件定义的
extern void fun2();
int main()
{
printf("This is main.\n");
fun2();
system("pause");
}
运行结果:
This is fun2.
This is main.
请按任意键继续…
说明:
- 首先,用方式1:include包含的方式 和方式2:extern声明外部函数的方式运行的结果是一样的。
- 其次,注意到两种方式分别命名fun.h文件和fun.c文件。而不能在方式1中命名fun.c然后include到main.c中,在方式2中命名fun.h然后extern void fun()。这是因为在VS2010中,在一个工程文件中,自动将.c文件都编译成.obj文件(这个可以到工程文件夹的debug文件里看到),而.h文件不会被编译。
所以,对文件命名的问题可以解释如下:方式1中,include直接把fun.h的文件内容完整复制到main.c,所以可以正常运行,如果是fun.c则会造成重定义(fun.obj和main.obj都有对fun2()函数的定义);方式2中,fun.c可以使fun2()得到编译,在main.c中extern 就能顺利编译通过,而命名fun.h则不然。
说完这两个栗子,下面我来详细总结我对多文件编译问题的理解。主要介绍:
- extern的用法
- # include 包含文件的问题
- 声明和定义,什么时候会出现重定义?