a.cpp
const unsigned char whatever[123] = { /* ... */ };
A.H
extern const unsigned char whatever[123];
b.cpp
#include "a.h"
unsigned char x = whatever[0];
// error: undefined reference to 'whatever'
为什么我会收到未定义的引用错误?如果没有const
,错误就会消失。
如何在多个翻译单元之间共享常量数组?
答案 0 :(得分:10)
这是人们遇到的一个怪癖,只是你定义了一个a.h头文件,它声明了一个包含123个字符的const数组,并为它指定了外部链接。当它被包含在b.cpp文件中时,你基本上承诺它将在其他一些翻译单元中找到它。
但是,每个const
变量都有一个黑暗的秘密 - 它被困在其定义的翻译单元中,因为它隐含地给出了静态链接。您承诺您的编译器whatever
将在多个翻译单元之间共享,但它实际上只忠于一个翻译单元而不喜欢共享。而且,嗯,你知道其余的。
通过在实现文件中明确声明extern
来解决。
答案 1 :(得分:4)
3.5/3
A name having namespace scope (3.3.5) has internal linkage if it is the name of
...
— an object or reference that is explicitly declared const and neither explicitly declared extern nor previously declared to have external linkage;
...
Vars喜欢
const int x = 10;
隐式定义为“静态”。
要使它们非静态(因此非内部),请使用“.c”文件中的“extern”修饰符。
尝试使用
extern const unsigned char whatever[123] = { /* ... */ };
答案 2 :(得分:1)
const在c ++中默认具有静态(内部)链接,在.c文件中也使用extern const This是一个随机的SO线程,有更多信息。或谷歌“c ++中的链接”。
答案 3 :(得分:0)
在C ++中,const是一个编译时const,例如
const int cc = 100;
int a[cc];
我们可以使用const在C ++中定义数组,但不能在C中定义。 由于它是const,无法更改哪个值,因此不需要在多个文件之间共享它们。所以,说,const有内部联系。
答案 4 :(得分:0)
要解决此问题,a.cpp
应该:
#include "a.h"
在定义whatever
之前。
如果范围中没有先前的声明,则const unsigned char whatever[123] = {...};
将具有内部链接。但是如果包含a.h
,则定义与先前的声明匹配。标头使用外部链接定义whatever
,定义与名称匹配。
正如其他人所提到的,您也可以将extern
放在定义中,以便在忘记#include "a.h"
时不会发生此错误。但是,最佳做法是包含声明我们试图公开定义的任何内容的标题。