2012-01-28 164 views
6

“的多重定义”我有下面的“常量”标头:链接问题与编译错误

/* constants.h */ 

#ifdef __cplusplus 
extern "C" { 
#endif 

#pragma once 

#ifndef CONSTANTS_H 
#define CONSTANTS_H 

const char * kFoo = "foo"; 
const char * kBar = "bar"; 

#endif 

#ifdef __cplusplus 
} 
#endif 

#include -ing在文件X.cY.c这个头。

请注意,我是而不是包括这在X.hY.h

将文件X.cY.c编译到目标文件中,该文件归档到名为libXY.a的静态库中。

当我包括X.hZ.hY.h,当我链接到libXY.a,我不能没有错误编译Z.c

/* Z.h */ 

#include "X.h" 
#include "Y.h" 

我在尝试编译Z.c当以下编译错误:

/path/to/libXY.a(X.o):(.data+0x0): multiple definition of `kFoo` 
/path/to/libXY.a(Y.o):(.data+0x0): first defined here 
/path/to/libXY.a(X.o):(.data+0x8): multiple definition of `kBar` 
/path/to/libXY.a(Y.o):(.data+0x8): first defined here 

我已经尝试设置kFookBarextern,但这没有帮助。

我将如何解决多个定义,当我只有(通过头文件保护#ifndef CONSTANTS_H),包括一旦常数?

+0

也许不是眼前的问题(不知道),但你应该删除伪造'#pragma once',并在你的头文件中放置适当的多重包含守卫。标准格式为'#ifndef MYHEADER_H #define MYHEADER_H ....#endif' – 2012-01-28 23:08:43

回答

9

我将如何解决多个定义,当我只包括一次常数(通过头文件保护的#ifndef CONSTANTS_H)?

有了这个constants.h

const char * kFoo = "foo"; 

kFoo的定义将在每一个翻译是#include小号constants.h发出。因此,多个定义,然后导致链接错误。

由于asaelr指出的(+1),你会解决这个问题是这样的:

constants.h

extern const char* const kFoo; 

常数。ç

const char* const kFoo = "foo"; 

(请注意,我也做了指针常量,这是通常你想在这种情况下该怎么做)

+4

还有一些可以考虑的选项。在当前的情况下,你提出的是正确的,但是:(A)'static const char * kFoo =“foo”;'没有单独的constants.c文件就可以工作;和(B)'static const char kFoo [] =“foo”;'可能是更精确的所需内容的再现(根据32位和64位指针,所用空间减少4或8个字节)。和(C)'extern const char kFoo [];'加constants.c包含'const char kFoo [] =“foo”;'可能是您的解决方案的适当变体。该代码可能不应该被允许执行'kFoo =“pqr”;'。 – 2012-01-28 23:18:47

+0

@JonathanLeffler +1我实际上已经开始撰写关于在这种情况下可以在后续编辑中做出的变体,但是我放弃了编辑,因为我和其他人在这个网站上已经这样做了。我认为'extern const char * const kFoo;'通常是最清晰的方式(使用C)来声明/记录你正在处理字符串常量。当然,这是主观的。 A + B)可以工作,但可能会导致二元膨胀。 constants.h +'k'前缀表明这是一个osx或ios项目(它通常以pch结尾)。在这种情况下编译和链接通常最简单。 – justin 2012-01-28 23:52:57

+0

除非实际上需要指针以及字符串,否则使用数组表示法优先于指针表示法。我同意静态版本可能导致代码膨胀并且通常不推荐。 (指针的版本也会导致代码膨胀,通过每个常量的指针大小增加可执行文件的数量。) – 2012-01-29 00:04:31

4

你不应该定义在头文件中的变量。在源文件中的一个定义它们,并在头文件声明它们(extern)。

(你写“我已经尝试设置kFoo和千巴为extern,但这并没有帮助。”我想,你没有在源文件中定义它们)

+0

如果我在'constants.c'中定义了变量,编译库时会得到“未定义的对'kFoo'的引用”错误。 (我正在编译'constants.c'到'constants.o'并将它包含在库中。)有什么想法? – 2012-01-28 23:07:57

+0

您是否定义或声明了它?你如何链接它? – asaelr 2012-01-28 23:11:22