【问题标题】:Why am I getting a multiple definition error on compile? [duplicate]为什么我在编译时出现多重定义错误? [复制]
【发布时间】: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


【解决方案1】:

在您的项目中,“main.c”和“parse.c”都包含#include "struct.h",因此两个这些源文件最终都包含以下内容:

struct planettype planname[plantot] = // List of planet types
{   // Name
    {"None"},
    {"Gas Giant"},
    {"Earth-like"},
    {"Uninhabitable"}
};

因此,在将组件对象模块链接到可执行文件时,planname 结构数组有两个定义。

要解决此问题,请将plannname(在头文件中)的定义转换为简单的声明,如下所示:

extern struct planettype planname[plantot]; // No initializer = just a declaration!

然后,将完整的定义(即初始化列表)添加到一个(并且一个) 您的源文件:either "main.c" "parse.c".

【讨论】:

  • 我明白了。这就解释了为什么我记得以前经常用 C 编写代码时总是遇到这些问题,因为我一直都是这样处理数组的。如果我试图过多地移动代码,事情总是会破裂。谢谢!
猜你喜欢
  • 1970-01-01
  • 2021-12-28
  • 1970-01-01
  • 2015-07-11
  • 2020-07-09
  • 2012-04-15
  • 1970-01-01
  • 1970-01-01
  • 2023-03-30
相关资源
最近更新 更多