4

我正在为嵌入式 power-pc 平台编程(使用 wind-river diab 编译器,如果这很重要)并且想将我的代码与预编译的目标文件 *.o 链接(当然是为同一平台编译的)。这些目标文件之一需要一个外部符号,我必须定义自己并链接到该 *.o 文件 - 否则链接器会抱怨:

Undefined symbol 'mySymbolName' in file 'precompiled.o'

但是,即使我用缺少的符号编译源文件(与预编译的 o.* 文件期望的签名相同:'unsigned char const [16]')并将其链接到 precompiled.o,链接器仍然会抱怨。myCFile.c:

unsigned char const mySymbolName[16] = {
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ,0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

我使用以下命令编译代码:

bin/dplus -g -Xdebug-dwarf3 -W:c++:.c -Xc++-abr -Xmake-dependency=0xd -Xsmall-data=0 -Xsmall-const=0 -Xlint=0x40 -O -tPPC5554FF:cross -I{some include pathes...}   -DTOOL_FAMILY=diab -DTOOL=diab -DPowerPC -DPPC5500  -o "myObjectFile.o" -c "myCFile.c"

编译器警告我, mySymbolName 已声明但从未使用(当然不是 - 它是从另一个目标文件引用的 - 所以我认为警告很好)。使用命令链接:

bin/dld   -tPPC5554FF:cross file.dld -o "output.elf"  myObjectFile.o precompiled.o

失败并出现错误:

Undefined symbol 'mySymbolName' in file 'precompiled.o'

使用 nm (当然对于特定的目标平台)我发现,我的符号在我编译的目标文件中不可见: nm 只是不显示任何内容。但是,我找到了一种以 nm 显示符号的方法。如果我在我的 c 文件中删除 'const' 说明符,则:

unsigned char mySymbolName[16] = {
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ,0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

nm 正确显示 mySymbolName。

所以我的问题是:这怎么可能?这是预期的行为 - 还是在不同平台上的行为不同?ANSI-C 编译器在编译时删除未引用的常量变量是否允许优化?

4

1 回答 1

4

您的 Diab 编译器调用似乎在强制 C++ 编译,C++ 中的语义const在很多方面与 C 中的语义不同。

在 C++const中,文件范围具有隐式静态(或内部)链接,因此不会放在目标文件的符号表中。这与 C 的行为不同,所以如果您使用 C 编译,它会产生您所期望的。

添加显式extern声明(或使用 C 编译):

extern unsigned char const mySymbolName[16] ;

有关更多信息,请参阅Ben Voigt 对const不久前提出的语义问题的回答。

于 2013-10-30T23:17:12.593 回答