2016-10-19 11 views
19

私は、誤って配列内の自己参照によってバグを作成しました。ここではコンセプトが似非常に単純化されたデモプログラムです:C++自己参照配列ですか?

#include <iostream> 
using namespace std; 

int kTest[] = { 
    kTest[0] 
}; 

int main() { 
    cout << kTest[0] << endl; 
} 

私はコンパイラエラーまたはこのコードでさえも警告もないを受け取ったことに驚きました!私の場合は、予期せぬ出力を生み出しました。ガベージメモリにアクセスしていますか?

私はどのような状況でこれが明確な出力を持っているのか不思議に思っていました。

を編集してください:kTeststaticの場合は違いがありますか? constはどうですか?どちらも?

+0

hmm。グローバルな 'int'sはゼロで初期化されているので、それが合法であるかどうか疑問に思います。 – NathanOliver

+0

言語標準がこの種の構文を許した状況下で。 –

+2

['int x = x;']とあまり変わりはありません(http://stackoverflow.com/questions/14935722/does-initialization-entail-lvalue-to-rvalue-conversion-is-int-xx-ub) 。 –

答えて

15
int kTest[] = { 
    kTest[0] 
}; 

関数内でローカルに宣言した場合それは、未定義の動作になります

int x = x; 

と全く同じに似ている、そうでない場合。

kTestがグローバル変数であるときは、よく定義されているようです。詳細は、the other answerを参照してください。

+1

これは意見ではないでしょうか?それともUBが標準で定義されていないのか? – Carcigenicate

+0

未指定ですか?私はそれがこれに似ていると思います: 'int x; x = x; '。 –

+0

@Carcigenicate、私はC++ 11の標準で 'int x = x;'が議論されていますが、OPの状況については何も言及していません。 –

8

これは未定義です。現在draftから引用:

[basic.start.static]/3

定数初期化を行わない場合、静的 貯蔵期間を持つ変数([basic.stc.static])またはスレッド保存期間 ([basic.stc.thread])はゼロで初期化されます([dcl.init])。一緒に、 ゼロ初期化と定数初期化は、スタティック 初期化と呼ばれます。他のすべての初期化は動的初期化です。 動的初期化が行われる前に、静的初期化を実行する必要があります。動的な初期化が開始したとき、すでにゼロに初期化されるので、0に初期化するように定義することができるkTestように見える私に

+0

あなたの解釈は意味があります。 'g ++'は、 'int x = x;'についてグローバルに定義されていると不平を言っていませんでしたが、関数に定義されていると不平を言っていました。 –

+1

なぜOPのグローバル初期化が動的であると仮定しますか? 'static int a [] = {1};は静的にしか初期化されません。 'a [0]'は0(静的)に初期化されず、1(動的)に再び初期化されます。 –

+0

@ PaulJ.Lucas:*ゼロ初期化と定数初期化をともに静的初期化と呼びます。他のすべての初期化は動的初期化です。* – krzaq