4

私たちの製品には、次のようなコードがあります。私によると、出力は「0 1 2 3」です。しかし、同様のコードの出力は '1 1 1 1' です。

for(i = 0 ;i < 5;i++){
    int j;
    if(i)
        printf("%d ",j);
    j = i;
}

私の理解では、 j は「for」ループの全期間中に一度だけスタックに割り当てられ、反復中に同じ値が使用されるということです。また、j の宣言を for ループの外に移動すると、期待どおりの結果が得られます。ここで何が欠けていますか?

PS - 個人のマシンで同じコードを実行すると、期待どおりの出力が得られます。しかし、本番では違います。

4

2 に答える 2

7

まず、自動ローカル変数の保存期間に関することを明確にするために、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 であり、iffalse と評価され、printf()スキップjされて初期化されます。次に、次の反復で を押すとprintf()jが初期化され、その後はすべてうまくいきます。

于 2016-02-12T06:37:15.743 に答える