链接错误(#ifndef 无法按预期工作)

Linking error (#ifndef doesn't work as expected)

本文关键字:工作 错误 #ifndef 链接      更新时间:2023-10-16

无法理解这里的问题是什么:我有一个main.cpp文件,其中包括:

#include "lexan.h"
...

lexan.h文件:

#ifndef _LEXAN_
#define _LEXAN_
enum Statements ...
//some function prototypes
...
struct TokensList {
    Statements statement;
    std::string value;
    struct TokensList *next;
};
struct TokensList *tokens = NULL;
#endif _LEXAN_

在lexan2.h:中

#include "lexan.h"
// and some function prototypes

问题是我得到链接错误2005:

1>lexan2.obj : error LNK2005: "struct TokensList * tokens" (?tokens@@3PAUTokensList@@A) already defined in lexan.obj
1>main.obj : error LNK2005: "struct TokensList * tokens" (?tokens@@3PAUTokensList@@A) already defined in lexan.obj

我的错误在哪里?我以为

#ifndef _LEXAN_
#define _LEXAN_

在lexan.h文件中可以保护我免受此类链接问题的影响。

您在头文件lexan.h中创建struct TokensList * tokens,然后在lexan.cpp&lexan2.cpp违反一个定义规则(ODR)

请注意,标头保护防止将同一标头包含在同一翻译单元中。在头文件中创建变量时,在包含头的每个翻译单元中都会创建一个同名变量的副本。这会导致项目中出现多个相同名称的变量,链接器会抱怨这些变量。

解决方案:
如果需要跨文件共享,则需要使用extern

如何使用extern
查看:
C中的外部变量是什么
如何正确使用c中的extern关键字?

正如注释中所暗示的那样,您违反了一个定义规则。

头文件应该声明变量;他们(几乎)永远不应该定义变量。您的头定义了变量tokens,这意味着给定程序中只有一个源文件可以使用该头,这不是预期的。

我建议看一下C中的extern变量是什么?关于如何处理标头中的变量的广泛(可能过于广泛)讨论。

但基本规则是:

  • 不要在标题中定义变量;只有声明它们

当然,这是假设全局变量是必要的。如果可以的话,避开他们。但是当它们是必要的时候,头应该声明而不是定义变量。

Include guards只会阻止您在每个翻译单元(源文件)中处理同一个标头两次

假设您有一个标头X.h,它包含了保护:

// x.h
#ifndef X_H
#define X_H
    // x.h stuff
#endif

您还有A.hB.h,每个都包括X.h:

// a.h
#ifndef A_H
#define A_H
    #include "x.h"
    // a.h stuff
#endif
// b.h
#ifndef B_H
#define B_H
    #include "x.h"
    // b.h stuff
#endif

然后我们有j.cppk.cpp:

// j.cpp
#include "a.h"
#include "b.h"
    // j.cpp stuff
// k.cpp
#include "a.h"
#include "b.h"
    // k.cpp stuff

这里,包含保护防止x.hj.cpp内被处理两次,类似于在k.cpp但是x.h仍然包括两次,每个翻译单元一次

int myGlobalInt; // x.h stuff

尽管您阻止j.cpp(和k.cpp)定义此变量两次,但每个变量仍然定义了一次。在链接时,链接器会同时找到它们并进行抱怨。

除了应该尽量避免全局变量之外,你想要的是:

extern int myGlobalInt; // x.h stuff

现在,每个翻译单元都被告知"某个地方存在myGlobalInt",您可以在自己选择的单个翻译单元中明确定义它。

另外,不要使用那些类型的收割台防护装置;以下划线后跟大写开头的名称以及以两个连续下划线开头的名称都是保留的。

相关文章: