链接错误(#ifndef 无法按预期工作)
Linking error (#ifndef doesn't work as expected)
无法理解这里的问题是什么:我有一个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.h
和B.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.cpp
和k.cpp
:
// j.cpp
#include "a.h"
#include "b.h"
// j.cpp stuff
// k.cpp
#include "a.h"
#include "b.h"
// k.cpp stuff
这里,包含保护防止 尽管您阻止 除了应该尽量避免全局变量之外,你想要的是: 现在,每个翻译单元都被告知"某个地方存在 另外,不要使用那些类型的收割台防护装置;以下划线后跟大写开头的名称以及以两个连续下划线开头的名称都是保留的。x.h
在j.cpp
内被处理两次,类似于在k.cpp
中但是x.h
仍然包括两次,每个翻译单元一次int myGlobalInt; // x.h stuff
j.cpp
(和k.cpp
)定义此变量两次,但每个变量仍然定义了一次。在链接时,链接器会同时找到它们并进行抱怨。extern int myGlobalInt; // x.h stuff
myGlobalInt
",您可以在自己选择的单个翻译单元中明确定义它。
- 当我在第一个循环中使用"auto"时,它工作正常,但是使用"int"它会给出错误,为什么?
- 这些是什么样的错误?即使我不在 Linux 上工作,我也遇到了 Linux 错误
- 当我从下面的代码中删除关键字 virtual 时,它可以正常工作,否则会出现错误。在这里"virtual"字的意义是什么?
- 实现 DFS 在较短的输入下工作正常,但在较大的输入下会抛出分段错误
- C++代码停止工作错误使用cout内部函数
- 我的代码无法正常工作。谁能指出错误?
- 请发现它在 dev 中工作的错误,但在 hackerrank 中不起作用
- 错误:三元运算符无法在对象中正常工作"cout"
- 一个非常简单的win32套接字代码,但工作错误
- 如何组织 git 工作流以修复错误并同时引入新功能
- emplace_back初始化列表错误,当初始化列表在独立变量上工作时
- 在调试配置中编译工作正常,但发布会给出链接错误
- .exe应用程序在windows10中创建新模块时抛出错误,但在windows7中工作正常
- 我的随机生成器是否不工作,或者我决定人/骨架是否击中对手的方式是否有错误
- 代码作为 C 文件工作,但不作为C++文件,错误:'__builtin_types_compatible_p'未在此范围内声明
- 当代码在Visual Studio C++中正常工作时,MSB6006错误
- 错误太多参数无法正常工作
- 为什么我必须将错误状态标志设置为 goodbit 才能使其工作
- 我的va_start/va_end宏工作错误
- 代码中没有错误,但是当我运行程序时,我得到“多项式.exe已停止工作”.错误