8

a.cpp

const unsigned char whatever[123] = { /* ... */ };

extern const unsigned char whatever[123];

b.cpp

#include "a.h"
unsigned char x = whatever[0];
// error: undefined reference to 'whatever'

为什么我会收到未定义的引用错误?没有const,错误就会消失。

如何在多个翻译单元之间共享一组常量?

4

5 回答 5

13

这是人们遇到的怪癖之一,只是您定义了一个 ah 头文件,该文件声明了一个 123 个字符的 const 数组,并为其分配了外部链接。当它被包含到 b.cpp 文件中时,您基本上是在保证它会在其他翻译单元中找到它的编译器。

但是,每个const变量都有一个不为人知的秘密——它被困在其定义的翻译单元中,因为它被隐式地赋予了静态链接。您承诺您的编译器whatever将在多个翻译单元之间共享,但它实际上只忠于一个翻译单元并且不喜欢被共享。而且,你知道其余的。

extern通过在实现文件中明确说明来解决。

于 2012-05-30T13:00:32.313 回答
5
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;
 ...

变量喜欢

 const int x = 10;

被隐式定义为“静态”。

要使它们成为非静态的(因此是非内部的),请在“.c”文件中使用“extern”修饰符。

尝试使用

extern const unsigned char whatever[123] = { /* ... */ };
于 2012-05-30T12:41:15.117 回答
1

const 在 c++ 中默认具有静态(内部)链接,在您的 .c 文件中也使用 extern const。
是一个包含更多信息的随机 SO 线程。或谷歌“c++中的链接”。

于 2012-05-30T12:40:52.933 回答
1

要解决这个问题,a.cpp应该这样做:

#include "a.h"

在定义之前whatever

如果范围内没有先前的声明,则将const unsigned char whatever[123] = {...};具有内部链接。但如果a.h包含,则定义与先前的声明相匹配。标头whatever使用外部链接定义,并且定义与名称匹配。

正如其他人所提到的,您也可以extern输入定义,这样如果您忘记#include "a.h". 但最好的做法仍然是包含声明我们试图公开定义的任何内容的标头。

于 2018-02-08T20:34:36.503 回答
0

在 C++ 中,const 是编译时 const,例如,

const int cc = 100;
int a[cc];

我们可以在 C++ 中使用 const 来定义数组,但在 C 中不能。由于是 const,无法更改其值,因此不需要在多个文件之间共享它们。因此,可以说, const 具有内部联系。

于 2012-05-30T14:03:46.850 回答