我有一种情况,使用与此类似的 C++ 编译器构建 C 代码库:
库文件
extern int const values[2] = {1, 2};
库文件
#include "lib.h"
主程序
#include <iostream>
extern int const values[2];
int main() {
std::cout << values[0] << ":" << values[1] << std::endl;
}
由于C++03 Standard Annex C Compatibility C.1.2 Clause 3中指出的内容,我不得不添加 extern 。 (用编译-fpermissive
将把它扫到地毯下。)
顺便说一句,它values
在 objdump 中的显示方式在 objdump 之前是这样的extern
:
$ objdump -t lib.o | grep values
0000000000000000 l O .rodata 0000000000000008 _ZL6values
$ objdump -t main.o | grep values
0000000000000000 *UND* 0000000000000000 values
...然后添加后是这样的:
$ objdump -t lib.o | grep values
0000000000000000 g O .rodata 0000000000000008 values
$ objdump -t main.o | grep values
0000000000000000 *UND* 0000000000000000 values
所以名称 mangling 被删除了,我们看到“L”变成了“G”,并且链接器不会抱怨values
未定义。
现在想象两个非常相似的文件的相同情况,以相同的方式修改:
tmp-exttypes.h
extern const REBYTE Reb_To_RXT[REB_MAX] = { /* bunch of stuff */ };
a-lib.c
extern const REBYTE Reb_To_RXT[REB_MAX];
这些是项目中仅有的两个 Reb_To_RXT 定义,构建干净。但它没有链接,当我 objdump 提到它的唯一两个文件时,我得到:
$ objdump -t a-lib.o | grep Reb_To_RXT
00000000 *UND* 00000000 Reb_To_RXT
$ objdump -t f-extension.o | grep Reb_To_RXT
00000080 l O .rodata 00000038 _ZL10Reb_To_RXT
它说 L,它的名字被破坏了。这并没有让这个简单得多的例子变得快乐。但是我想知道每次出现时都带有extern怎么会发生这种情况。我是否正确地相信这是一支确凿的证据……而且通常不应该发生仅声明为 extern 的东西在任何地方都不应该具有本地联系?