2

以下を使用して、Debian から arm-linux ターゲットにいくつかのファイルをクロスコンパイルしようとしているときに、いくつかの奇妙な動作が発生しています (まあ、説明があると思います)。

$ arm-linux-gnueabi-gcc --version

$ arm-linux-gnueabi-gcc (Debian 4.3.5-4) 4.3.5

コンパイル中に次のエラー メッセージが表示されます。

dsblock1.c:167: error: non-static declaration of ‘HaveEventIterated_’ follows static declaration
ss2dym.c:778: error: previous declaration of ‘HaveEventIterated_’ was here

対応する行は次のとおりです。

ss2dym.c:778 :
extern long HaveEventIterated_;

"redeclaration" dsblock1.c:167:
long HaveEventIterated_=0;

だからここに私が得られないことがあります.

しかし、「extern」宣言は静的関数内にあります。私の推測では、これはある種の継承された動作なのでしょうか?!

質問は次のとおりです: - 私の推測が正しければ、背景の話を誰か説明してもらえますか? -たとえば、ネストされたスコープシフトやその他の魔法を可能にするトリッキーなコンパイラフラグを使用して、それを回避する簡単な方法はありますか?

ヘッダーを作成し、これらすべての extern 宣言をニュートラル スペースに配置する可能性が最も高いことはわかっていますが、何百ものエラーといくつかのファイルがあります。そして、このコードは MSVC++ を使用して適切にコンパイルされることを確認しました (これには他のスコープ制約があることはわかっていますが、arm-g++ を使用するとさらに多くの問題があります)。したがって、これらすべての部分を書き直すよりも簡単な何らかの解決策が必要です。 ...

ところで:これらすべての「再宣言」のスコープを変更する簡単な方法があります。これは、それらすべての前に次のようなマクロがあるためです。

MY_MACRO long HaveEventIterated_=0;

そしてatmでコンパイルします-DMY_MACRO=

すっごく誰か?:)

4

1 に答える 1

2

このexternキーワードは、識別子に以前の可視宣言と同じリンケージ1を与えるか、以前の可視宣言がない場合は外部リンケージを与えます。(確かに、これは言語の奇妙な癖です。)

したがって、この問題は、コンパイラが の 778 行目に到達する前に到達する の3 番目の(またはおそらく「最初の」と言うべき) 宣言が原因で発生する可能性が最も高いです。その 3 番目 (または最初) の宣言では、キーワードを使用して、識別子に内部リンケージを与えます。2 番目の宣言 withでは、同じ変数の内部リンケージが指定され、3 番目の宣言 (リンケージを指定する storage-class キーワードがない) では、変数の外部リンケージが指定され、エラーが発生します。HaveEventIterated_ss2dym.cstaticextern

問題を再現する短い例を次に示します (別の gcc で動作しますが、動作は同じです)。

$ cat foo2.c
static int var;
extern int var;
int var = 0;
$ gcc -c foo2.c
foo2.c:3: error: non-static declaration of 'var' follows static declaration
foo2.c:2: error: previous declaration of 'var' was here

1補足: 前の可視宣言にリンケージがない場合、外部リンケージが得られます。これは、そのブロックの外側の変数が自動期間を持つブロック内の変数を再宣言する場合にのみ発生します。つまり、関数内の「ローカル」または「スタック」変数です。

void f(void) {
    int v;
    {
        extern int v;

ここにはリンケージのない前の可視宣言があるため、最も内側vには外部リンケージがあります。同じ翻訳単位に with 内部リンケージがある場合v、効果は未定義です。(もちろんf()、とにかく、そもそも誰もコードを書くべきではありません:-))

于 2013-10-03T10:43:36.460 に答える