【发布时间】:2016-08-10 02:10:09
【问题描述】:
我的文件结构如下:
X.h
#pragma once
#include "Y.h"
int ONE = 1;
int combine();
X.c
#include "X.h"
int combine()
{
return ONE + TWO;
}
Y.h
#pragma once
int TWO = 2;
Y.c
#include "Y.h"
Main.c
#include "X.h"
int main()
{
int fusion = combine();
return 0;
}
我收到以下错误:
LNK1169 one or more multiply defined symbols found
LNK2005 _ONE already defined in Main.obj
LNK2005 _TWO already defined in Main.obj
KLNK2005 _TWO already defined in Main.obj
这是零意义。如果我们从Main.c 开始,编译器必须包含X.h。然后编译器查找与X.h 关联的C 文件。在X.c 中,它需要包含X.h,但#pragma once 应该提防这种情况。然后它需要包含Y.h。它查找 C 文件并找到 Y.c,它说包含 Y.h,但 Y.h 已经包含在内。然后,它返回到 Main.c 并且应该成功编译......但是没有。
我可以将/FORCE 添加到我的项目设置中,这使我的代码可以完美运行,但仍会输出:
ONE has already been defined, second definition ignored.
【问题讨论】:
-
然后编译器查找与 X.h 关联的 C 文件。 -- 什么?你是从哪里想到这个的?
-
我不知道从哪里开始解开你对 w.r.t 头文件的所有错误。你陈述了你认为发生的事情,而这些事情都没有发生。编译器不会搜索其他
C模块以查看它们包含的内容。 -
@Hatefiend 不。您告诉编译器要编译哪些
.c文件 - 直接在命令行上或通过像 Make 这样的构建系统。编译器不会根据头文件自动查找.c文件。至于 pragma once,它可以防止在 single 源文件中多次包含。它不会阻止包含来自 不同 源文件的相同头文件。后者是您所拥有的,也是导致多定义链接错误的原因。 -
@Hatefiend 这不是嘲笑。你提出了一个完全错误的场景,鉴于此,我们需要从一开始就对构建过程、头文件等进行解释。
-
一般来说,每当您询问编译或链接问题时,如果您还提供有关平台和编译器的信息,以及有关构建的任何可能非典型的信息(例如符号链接),它会有所帮助。我严重怀疑这里的情况,pragma once 很常见,但严格来说不是标准的一部分,预编译链如何实现文件识别也不是(例如,如果它使用文件标识而不是解析它可以被打破符号链接,而 ifdef 守卫不会)。
标签: c