ローカル変数 i がこの C プログラムで初期化されていないにもかかわらず、多くのシステムが出力する理由を理解しようとしています0 1 2 3 4 5 6 7 8 9
。どんな助けでも大歓迎です!
void foo() {
int i;
printf("%d ", i++);
}
int main() {
int j;
for (j = 1; j <= 10; j++) foo();
}
ローカル変数 i がこの C プログラムで初期化されていないにもかかわらず、多くのシステムが出力する理由を理解しようとしています0 1 2 3 4 5 6 7 8 9
。どんな助けでも大歓迎です!
void foo() {
int i;
printf("%d ", i++);
}
int main() {
int j;
for (j = 1; j <= 10; j++) foo();
}
動作は未定義です。統計は無関係です。スタックのレイアウトと初期化が原因である可能性がありますが、他の理由による可能性もあります。
たとえば、次のように仮定します。
i
は、レジスタとしてではなくスタックに割り当てられます。そのような場合i
、毎回スタック上の同じ場所を参照し、0 として開始し、スタック上の同じ場所を毎回 1 ずつ増やします。
スタック上に変数i
が作成され、初期化されていません。したがって、予測できないガベージ値が含まれています。幸いなことに、あなたの場合、そのガベージ値は最初は 0 です。別のシステムで実行すると、異なる値のセットが得られます。動作は確かに未定義です。
forループでその関数を呼び出す以外に何もしていないので、幸運なことに、その変数i
は毎回破棄され、同じメモリ空間が再割り当てされます。そのため、反復間でもその値が保持されます。
私のシステムでは、これらの値が得られます。
2009288233
2009288234
2009288235
2009288236
2009288237
2009288238
2009288239
2009288240
2009288241
2009288242
これは、関数内のローカル変数が同じメモリ ブロックから繰り返し割り当ておよび解放されていることが原因である可能性があります。これが、出力が繰り返しインクリメントされる理由です。
初期値ゼロは運です。他のガベージ値である可能性があります。
動作は未定義であり、別のシステムでは機能しません。
他の人が指摘しているように、これは未定義の動作であるため、確実な答えはありません。
そうは言っても、あなたが得る最も一般的な値は0から9であるというのはおそらく正しいでしょう。これは、プログラムがスタックを受け取る前に、OSがスタックによって占有されているメモリをゼロにしたために起こります。foo()
行われた最も深い呼び出しを表します。したがって、OSがゼロにした後に触れられていないメモリを使用しているため、最初の呼び出しでは、まだゼロが含まれている可能性があります。
後続の各呼び出しでは、スタック上の同じ場所を占める可能性が高いため、後続の各呼び出しの開始時に、前の呼び出しの終了時の値から開始する可能性があります。
これは未定義の動作であり、これはまったく保証されていませんが、確かに、少なくとも少しはそうではない可能性があります。
これは単純なプログラムなので、同じメモリ位置が i で使用されていることは幸運です。これは初期化されていないため、以前の値が取得されます。
ただし、これは未定義です。このバグを拾うには、警告を付けてコンパイルする必要があります。