まず、自動ローカル変数の保存期間に関することを明確にするために、C11
標準の章 §6.2.4 を引用させてください (強調鉱山)
識別子がリンケージおよびストレージ クラス指定子なしで宣言されているオブジェクトには、static
自動ストレージ期間があります[...]
と、
可変長配列型を持たないこのようなオブジェクトの場合、その有効期間は、関連付けられているブロックへのエントリから、そのブロックの実行が何らかの方法で終了するまで延長されます。(囲まれたブロックに入るか、関数を呼び出すと、現在のブロックの実行が中断されますが、終了しません。)ブロックに再帰的に入ると、オブジェクトの新しいインスタンスが毎回作成されます。オブジェクトの初期値は不定です。
したがって、コードでは、反復ごとに の新しいインスタンスが取得されますj
。何も保持されません。
あなたのコードでは、
int j; //not initialized
if(i)
printf("%d ",j); //this one here
j
不確定な値を持つ、初期化された自動ローカル変数を使用しようとしています。未定義の動作を引き起こします。
に従ってC11
、章§6.7.9
自動保存期間を持つオブジェクトが明示的に初期化されていない場合、その値は不確定です
および関連、UB については、附属書 §J.2
自動保存期間を持つオブジェクトの値は、不定の間使用されます。
コードが UB に達すると、とにかく出力を正当化できなくなります。
OTOH、j
ループの外側で宣言すると、関数スコープがあります。次に、上記の場合とは異なり、ループのすべての反復に対して1 つのインスタンスのみが存在します。j
実行フローに従って、初回i
は 0 であり、if
false と評価され、printf()
スキップj
されて初期化されます。次に、次の反復で を押すとprintf()
、j
が初期化され、その後はすべてうまくいきます。