VectorLu

C 语言多文件注意事项

本文解决以下问题:

  1. 如何防止头文件被重复包含?
  2. 已经防止头文件被重复包含,如何防止因全局变量重复定义而引起的链接错误,报错如 duplicate symbol _test in …? 如果想了解全局变量和局部变量的相关细节,可以看看这篇 C 语言存储类详解

防止头文件被重复包含

如果头文件 first.hsecond.h 中都包含了头文件 duplicate.h,那么当同时引入前两个头文件时,duplicate.h 会被隐式地包含两次。

在大型的项目中,往往会引入很多头文件,为了防止上述问题,要在每一个头文件的程序头尾加上条件编译。

duplicate.h
1
2
3
4
5
6
7
8
9
#ifndef headername_h
#define headername_h
// insert all code here
// 这里是你写的代码,下面还有一句预定义
// 注意下面这句预定义不要掉了
// 注意不要把代码写到下面那句定义的后面
#endif

防止全局变量被重复定义

全局变量重复定义的原因和报错内容

虽然上述方法可以防止整个头文件被重复包含,但是编译器是按 .c 文件为单位编译成 .o 文件( Linux 系统)或者 .obj 文件( Windows 系统),然后将这些 .o 文件链接起来,最后与运行库链接形成可执行文件。

在两个 .c 文件中包含同一个 .h 文件,跟条件编译没有关系。在头文件中定义了全局变量,而多个 .c 文件中引入这个头文件,每个 .c 文件中都有这个全局变量,在链接的时候就会报重复定义变量的错误。

1
duplicate symbol _duplicateVariableName in FileAddress

解决方法

在 .c 文件中声明并初始化全局变量,在 .h 文件中用extern声明这个全局变量,注意只是声明,不能初始化。在其他需要这个全局变量的 .c 文件中引入这个头文件,就会包含这个extern的变量声明,在生成目标代码的时候,编译器就会链接到定义该全局变量的 .c 文件。如下示例:

test_extern.h
1
2
3
4
5
6
7
8
9
#ifndef test_extern_h
#define test_extern_h
#include <stdio.h>
// 声明外部链接
extern double test;
double test_extern_method(void);
#endif /* test_extern_h */
test_extern.c
1
2
3
4
5
6
7
8
9
#include "test_extern.h"
// 定义全局变量 test
double test = 0.0;
double test_extern_method(void)
{
test++;
return test;
}
main.c
1
2
3
4
5
6
7
8
9
10
#include "test_extern.h"
// 包含了以上头文件就声明了全局变量 test
// 编译器会链接到 test_extern.c 中的全局变量
int main(int argc, const char * argv[]) {
test+= 1.0;
test = test_extern_method();
printf("%lf\n", test);
return 0;
}
您的支持将鼓励我继续创作!

热评文章