1

これに相当する 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と、敷物の下でこれを一掃します。)

ちなみに、valuesobjdump での表示方法の違いは、次のようになり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としてのみ宣言されたものにローカルリンケージを持たせるべきではないということはどこにもありませんか?

4

2 に答える 2

3

私はあなたが何を求めているのか理解できません。

しかし …

持つ

extern int const values[2] = {1, 2};

ヘッダーファイルでは、そのヘッダーが複数の翻訳単位に含まれている場合、UB があります。ほとんどの場合、リンクエラーが発生しますが、必ずしもそうとは限りません。

1つの解決策:ヘッダーで配列を宣言します。

extern int const values[2];

ただし、実装ファイルで(初期化子を使用して)定義します。

もう 1 つの解決策は、テンプレートのトリックまたはインライン関数のトリックを使用して、ヘッダー ファイルで配列を定義することです。

インライン関数のトリック:

typedef int const Values[2];

inline Values& valuesRef()
{
    static Values   theValues = {1, 2};
    return theValues;
}

static Values& values = valuesRef();
于 2012-12-17T05:29:58.763 に答える
1

はい正解。

あなた (私) が編集していたファイルは自動生成され、実際にはきれいな make によって破棄されました。これは、思考プロセスを書き留めている途中で気づきました。その特定のヘッダーに表示される「tmp」は、「一時的、編集しないでください」を示唆するはずであり、使用しているエディターでファイルがリロードされない場合、混乱を招く可能性があります。

(とにかく、制度的知識のために一連の思考を終えました。:-P)

于 2012-12-17T04:44:03.023 に答える