2

ループの本体で文字配列を宣言するCのループについて考えてみます。各反復で、配列の文字は最後に到達するまで変更されます。最後に、変数が出力されます。説明は次のコードに拡張されます。

#include <stdio.h>

int main(void) {
    int i = 0;
    for (;;) {/* same as: while(1) { */
        char x[5];
        x[i] = '0' + i;
        if (++i == 4) {
            x[i] = '\0'; /* terminate string with null byte */
            printf("%s\n", x);
            break;
        }
    }
    return 0;

0123多くの人が出力として期待するかもしれません。しかし、何らかの理由で、GCC 4.7は、最適化を有効にした(およびそれ以降)コンパイル時にそれを行いません-O1。代わりに、ランダムデータを文字配列の最初のバイトに配置します。これは次のようになります。

| 0  |  1  |  2  |  3  |  4   |
|     RANDOM     | '3' | '\0' |

これは言語の観点からは論理的な動作だと思います。ブロックが終了すると自動変数がなくなるため、上記の「ランダムな」動作が予想されます。

正しい振る舞いは何でしょうか?ループの外側の宣言を移動すると「修正」されることは知っていxますが、このスニペットの動作については何も言えません。実際の問題はNetfilterのバグです。

4

4 に答える 4

4

配列はループ本体のスコープ内で宣言されているため、ループの反復ごとに自動ストレージ領域に新しい配列が割り当てられていると考えることができます。その単一化された配列の内容は、現在の反復中に割り当てたインデックスの文字を除いて未定義であるため、不確定な値が表示されます。

C99標準、セクション6.7.8:自動保存期間を持つオブジェクトが明示的に初期化されていない場合、その値は不確定です

最適化をオフにすると、配列は自動ストレージの同じ場所に配置されるため、プログラムは幸運になります。ただし、これは決して保証されません。

次のように、配列をループの外側に移動します。

int i = 0;
char x[5];
for (;;) {
    x[i] = '0' + i;
    if (++i == 4) {
        x[i] = '\0'; /* terminate string with null byte */
        printf("%s\n", x);
        break;
    }
}
于 2012-07-25T13:35:14.747 に答える
2

これはブロックスコープの問題です。ループ本体は、で示されるブロックであり、{}ループの反復ごとに出入りします。ブロックに入るたびに、(概念的には)x内容が指定されていない新しいものを取得します。

を設定x[3] = '3'しただけで、が呼び出さx[4] = '\0'れた反復でprintfは、これら2つの配列メンバーのみが明確に定義されたコンテンツを持ちます。残りの部分には、を含む任意の文字列を含めることができる'\0'ためprintf、最大2の長さの任意の文字列を出力でき、オプションで他の文字と。を続けることができ3ます。

于 2012-07-25T13:36:01.360 に答える
0

自動変数は、宣言されたスコープが終了した後にクリーンアップされるため、これは期待どおりに出力されます(ランダムな文字配列)。修正するには、ループxのスコープ外に移動します。for

于 2012-07-25T13:35:00.933 に答える
-1

配列には反復ごとにメモリが割り当てられ、最後の反復でのみ取得された値が含まれます。

于 2012-07-25T13:58:02.247 に答える