これに相当する C++ コンパイラを使用して C コードベースを構築する状況があります。
lib.h
extern int const values[2] = {1, 2};
lib.c
#include "lib.h"
main.c
#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 での表示方法の違いは、次のようになり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
したがって、名前マングリングは削除され、「L」が「G」に変わり、リンカはvalues
未定義であることについて文句を言いません。
同じ状況で、2 つの非常によく似たファイルを同じ方法で変更したとします。
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];
これらは、クリーンにビルドされた、プロジェクト内の 2 つの Reb_To_RXT 定義のみです。しかし、それはリンクしていません。それについて言及している2つのファイルのみを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としてのみ宣言されたものにローカルリンケージを持たせるべきではないということはどこにもありませんか?