我看到了一些类似的问题,但在其中没有一个,#ifndef HEADER_H
提到了.
我有一个头文件和2个C文件:
constants.h
main.c
mylib.c
在constants.h中:
#ifndef CONSTANTS_H
#define CONSTANTS_H
const int NUM_OF_ITEMS = 22;
#endif
Run Code Online (Sandbox Code Playgroud)
在mylib.c中:
#include "constants.h"
... code ...
Run Code Online (Sandbox Code Playgroud)
在main.c中:
#include "constants.h"
int main() {
... code ...
}
Run Code Online (Sandbox Code Playgroud)
当我使用命令编译时:gcc main.c mylib.c -o main
,我收到以下错误:
/tmp/ccl55fv3.o:(.rodata+0x0): multiple definition of `NUM_OF_ITEMS'
/tmp/ccyZhu6F.o:(.rodata+0x0): first defined here
collect2: ld returned 1 exit status
Run Code Online (Sandbox Code Playgroud)
#ifndef
,为什么会这样?constants.h
为声明和constants.c
作业外,还有什么可做的吗?包含头文件的每个转换单元(读取.c源文件)都会生成全局变量的新定义.这就是链接器对有多个定义的原因.请记住,#include
执行包含文件的文本插入.从编译器的角度来看,每个翻译单元都包含不同的定义NUM_OF_ITEMS
.
您需要在一个翻译单元中定义它.您可以考虑添加一个constants.c
包含定义的NUM_OF_ITEMS
,并在头文件中只留下一个声明.
或者你可以使用宏:
#define NUM_OF_ITEMS 22
Run Code Online (Sandbox Code Playgroud)
或者正如Jens在下面的评论中建议的那样,枚举常数.
或者你自己建议,通过static
链接使对象在每个翻译单元内部.
需要包含防护来防止编译期间单个翻译单元的多重包含。另一方面,您遇到的错误是链接器错误 - 因为您有多个包含相同定义的翻译单元(目标文件)。
在 C 中,通常将#define
常量定义为宏。这在类型安全方面有缺点。或者,您可以做一到两件事:
通过声明来本地化每个翻译单元中的常量static
:
static const int NUM_OF_ITEMS = 22;
Run Code Online (Sandbox Code Playgroud)声明它extern
,然后在单个翻译单元中定义:
extern const int NUM_OF_ITEMS ;
Run Code Online (Sandbox Code Playgroud)
常量.c:
#include constants .h
const int NUM_OF_ITEMS = 22;
Run Code Online (Sandbox Code Playgroud)选项 1 是 C++ 中的常见做法,其中 的语义const
与 C 有所不同,或者至少定义更清晰,并且除非引用或指针指向常量,否则常量将被插入到代码中,就好像是宏一样- 即“变量”不会有明显的存储。在 C 代码中,这可能会发生,也可能不会发生,但无论如何它都会工作,但效率可能会稍低。