web-dev-qa-db-ja.com

C ++での初期化されていない変数の動作

私は自分自身をチェックしました、私はこのようなプログラムを書きました

int main() {
 int i;
 cout << i;
 return 0;
}

プログラムを数回実行したところ、結果は常に同じで、ゼロでした。 Cで試してみましたが、結果は同じでした。

しかし、私の教科書には

関数内で定義された変数を初期化しない場合、変数値は未定義のままになります。つまり、要素は、メモリ内のその場所に以前存在していた値を引き継ぎます。

プログラムが常に空きメモリ位置を変数に割り当てる場合、これはどのように可能ですか?どうしてゼロ以外のものになるのでしょうか(デフォルトの空きメモリ値はゼロだと思います)。

13
omidh

プログラムが常に空きメモリ位置を変数に割り当てる場合、これはどのように可能ですか?どうしてゼロではなく何かになるのでしょうか?

実用的な実装の例を見てみましょう。

ローカル変数を保持するためにスタックを利用するとしましょう。

void
foo(void)
{
        int foo_var = 42;
}

void
bar(void)
{
        int bar_var;
        printf("%d\n", bar_var);
}

int
main(void)
{
        bar();
        foo();
        bar();
}

上記の完全に壊れたコードは、その要点を示しています。 fooを呼び出すと、foo_varが配置されたスタック上の特定の場所が42に設定されます。barを呼び出すと、bar_varがその正確な場所を占めます。実際、コードを実行すると0と42が出力され、初期化しない限りbar_var値を信頼できないことがわかります。

ここで、ローカル変数の初期化が必要であることは明らかです。しかし、mainは例外でしょうか?スタックで遊んで、結果としてゼロ以外の値を与えることができるものはありますか?

はい。 mainはプログラムで実行される最初の関数ではありません。実際、すべてをセットアップするために必要な作業はトンあります。この作業のいずれかがスタックを使用し、それにゼロ以外のいくつかを残す可能性があります。異なるオペレーティングシステムで同じ値を期待できないだけでなく、現在使用しているシステムでも突然変化する可能性があります。利害関係者は「ダイナミックリンカー」をグーグルで検索できます。

最後に、C言語標準には用語スタックすらありません。ローカル変数の「場所」を持つことは、コンパイラーに任されています。与えられたレジスターにたまたま入っていたものからランダムながらくたを取得することさえできます。それは本当に完全に何でもである可能性があります。実際、未定義の動作がトリガーされた場合、コンパイラーは自由に好きなことを行うことができます。

15

関数内で定義されている変数を初期化しない場合、変数値は未定義のままになります。

このビットは本当です。

つまり、要素は、メモリ内のその場所に以前存在していた値を引き継ぎます。

このビットはそうではありません。

実際にはこれが発生することがあります。プログラムの特定の実行について、ゼロになるまたはゼロにならないがこの理論に完全に適合することを理解する必要があります。

理論的には、コンパイラは必要に応じて実際にその整数にランダムな初期値を割り当てることができるため、これについて合理化しようとしてもまったく意味がありません。しかし、「要素は、メモリ内のその場所に以前に存在していた値をとる」と仮定したかのように続けましょう…

どうしてゼロではなく何かになるのでしょうか(デフォルトの空きメモリ値はゼロだと思います)。

さて、これはあなたが仮定したときに起こることです。 :)

このコードは、ポインターが初期化されていない状態で使用されるため、Undefined Behavior(UB)を呼び出します。

-Wallのような警告フラグが使用されると、コンパイラは警告を発行する必要があります。

warning: 'i' is used uninitialized in this function [-Wuninitialized]
  cout << i;
          ^

たまたま、この実行時に、システムの値が0でした。つまり、変数が割り当てられたガベージ値がたまたま0であったのは、そこに残っているメモリがそのように示唆しているためです。

ただし、 カーネルゼロは比較的頻繁に表示されます であることに注意してください。つまり、システムの出力としてゼロを取得できることは非常に一般的ですが、それは保証されておらず、約束されるべきではありません。

3
gsamaras

静的変数とグローバル変数はゼロに初期化されます。

Global:
int a;  //a is initialized as 0

void myfunc(){
   static int x;     // x is also initialized as 0
   printf("%d", x);}

非静的変数またはauto変数、つまりローカル変数はindeterminate(不確定は通常、何でもできることを意味します。ゼロの場合もあれば、次の値の場合もあります)そこでは、プログラムがクラッシュする可能性があります)。値を割り当てる前にそれらを読み取ると、未定義の動作が発生します。

void myfunc2(){
   int x;        // value of x is assigned by compiler it can even be 0
   printf("%d", x);}

これは主にコンパイラーに依存しますが、一般的にほとんどの場合、値はコンパイラーによって0と見なされます。

1
S.I.J