【发布时间】:2021-08-06 16:38:06
【问题描述】:
我正在使用 C 语言工作,这是我很长一段时间以来第一次使用 C 语言编写代码。我很难找出为什么在编译时会出现多重定义错误。这是一些示例代码,足以重现错误。
文件:main.c
#include <stdio.h>
#include "struct.h"
int main()
{
parse();
}
文件:struct.h
#ifndef STRUCT_H
#define STRUCT_H
#define plantot 4
void parse();
struct planettype
{
char name[30]; // Name of planet
};
struct planettype planname[plantot] = // List of planet types
{ // Name
{"None"},
{"Gas Giant"},
{"Earth-like"},
{"Uninhabitable"}
};
#endif // STRUCT_H
文件:parse.c
#include <stdio.h>
#include "struct.h"
void parse() {
printf("I'm not parsing a thing!\n");
};
我尝试编译该代码并得到:
mingw32-gcc.exe -Wall -g -c C:\Projects\TW-test\parse.c -o obj\Debug\parse.o
mingw32-g++.exe -o bin\Debug\TW-test.exe obj\Debug\main.o obj\Debug\parse.o
obj\Debug\parse.o:parse.c:(.data+0x0): multiple definition of `planname'
obj\Debug\main.o:main.c:(.data+0x0): first defined here
collect2.exe: error: ld returned 1 exit status
我有适当的标题保护,可以防止这种确切的事情发生。为什么会这样呢?我花了几个小时试图弄清楚这一点,但不能。在我实际的完整项目中,我在 struct.h 中的几个结构上得到了这个,但我想如果我可以为这个修复它,它会为所有这些修复它。如果有什么不同,我正在使用 Code::Blocks 来编写和编译代码。
我错过了什么?为什么这段代码编译不出来?
【问题讨论】:
-
您违反了单一定义规则,因为
planname不是一个纯粹的声明,而是一个定义,因为它包含一个初始化程序。因此,每个包含都会导致创建另一个定义。 -
因为您在标头中定义变量并将其包含在 2 个编译单元中。你应该只在你的头文件中保留声明并将定义移动到 C 文件中。
-
@jxh 这不是 100% 正确的。
planname是一个定义的原因是它不是extern。即使没有初始化,它仍然是一个定义。 -
@SergeyA:是的。如果不存在其他定义,C 允许将非
extern未初始化的声明视为定义。
标签: c compilation