include
include
是C语言中的预处理指令,用来导入头文件(.h
)或源文件(.c
),include
指令的语法如下:
#include <stdio.h> // 导入系统头文件,使用<>包裹
#include "mylib.h" // 导入自定义头文件,使用""包裹
除了可以导入头文件之外,还可以直接导入源文件,但是这种方式十分少见(不推荐)
// main.c
#include "mylib.c"
函数定义与声明
c语言规定,函数可以声明多次,但是只能定义一次,函数的声明和定义的区别如下:
// 函数声明
int add(int a, int b);
// 函数定义
int add(int a, int b) {
return a + b;
}
为什么不推荐直接导入源文件
如果在多个源文件中导入了同一个源文件,那么这个源文件中的函数就会被重复定义,这样会导致编译错误。
比如在mylib中定义了一个add函数,在test.c中定义了一个sum函数,这个sum函数中有使用了add函数
// mylib.c
int add(int a, int b) {
return a + b;
}
// test.c
#include "mylib.c"
int sum(int a, int b) {
return add(a, b);
}
当在main.c中同时导入了mylib.c和test.c时,就会导致add函数被重复定义,从而导致编译错误
// main.c
#include "mylib.c"
#include "test.c"
int main() {
return 0;
}
include
会将被导入的文件的内容直接复制到导入文件中,所以在main.c中,add函数被定义了两次,从而导致编译错误。
// main.c
int add(int a, int b) {
return a + b;
}
// 重复定义
int add(int a, int b) {
return a + b;
}
int sum(int a, int b) {
return add(a, b);
}
int main() {
return 0;
}
将声明和定义分离
为了解决重复定义的问题,我们可以将函数的声明和定义分离,将函数的声明放在头文件中,将函数的定义放在源文件中,这样就可以避免重复定义的问题。
// mylib.h
int add(int a, int b);
// mylib.c
#include "mylib.h"
int add(int a, int b) {
return a + b;
}
使用时,只需要导入头文件即可
// main.c
#include "mylib.h"
int main() {
int a = 1, b = 2;
int c = add(a, b);
printf("%d\n", c);
return 0;
}
更高级的头文件
上面的方案貌似解决了重复定义的问题,但当函数的定义也发生在头文件中时,还是会导致重复定义的问题,比如下面的代码:
// mylib.h
int add(int a, int b) {
return a + b;
}
// main.c
#include "mylib.h"
#include "mylib.h" // 重复导入
int main() {
int a = 1, b = 2;
int c = add(a, b);
printf("%d\n", c);
return 0;
}
编译时,会将头文件中的内容复制到源文件中,当头文件被包含多次时,就会导致函数的定义被重复定义,从而导致编译错误。
为了解决这个问题,我们可以使用#ifndef
和#define
来避免头文件被重复导入,这样就可以避免函数的重复定义。
// mylib.h
#ifndef MYLIB_H // 会在include之前检查是否已经定义了MYLIB_H
#define MYLIB_H
int add(int a, int b) {
return a + b;
}
#endif
// main.c
// 未定义MYLIB_H,所以会导入头文件
#include "mylib.h"
// 已经定义了MYLIB_H,所以不会导入头文件
#include "mylib.h" // 不会重复导入
int main() {
int a = 1, b = 2;
int c = add(a, b);
printf("%d\n", c);
return 0;
}
一个常见的文件结构
经过上面一系列的铺垫,我们可以将一个项目的文件结构设计如下:
.
├── main.c
├── mylib.c
└── mylib.h
其中,main.c
是主文件,mylib.c
是自定义的库文件,mylib.h
是自定义的头文件,mylib.c
和mylib.h
一起组成了自定义的库。
# 编译命令
gcc -o main main.c mylib.c