2016-12-11 13 views
1

は下の下でコードを切り取ら:func_1()未定義変数とコンパイラの最適化

---それがスタックにAを押して40にそのメモリの値を設定しますスタックからAをポップします。

func_2()後---それが再びスタックにAを押して前に設定された値を継承し、我々がBfunc_2()で名前Aを変更した場合、プリントアウトは、値が40

void func_1() 
{ int A = 40;} 

void func_2() 
{ int A; printf("%d/n",A);} 

void main (void) 
{ 
    func_1(); 
    func_2(); 
} 

になりますでしょうスタックの使用をテストし、名前付き変数のプールの使用をテストするために余分なコードを置く:私のコンピュータ上で

int A; printf("%d\n", A); 

、それは、Bが40であると言いますコンパイラがコンパイルされたコード(?)を最適化するために再利用される名前付き変数のプールを持っている場合、なぜAに0が得られたのですか? コンパイラはいつプールを使用しますか?

私の質問は、このスライドに基づいています:http://www.slideshare.net/olvemaudal/deep-c/131-I_am_now_going_to

+0

これは、コンパイラに大きく依存するように聞こえます。しかし、私が正しく理解していれば、 'func_2'で' B'と 'A'を出力します。つまり、' B'を最初に割り当てるので、スタックに最後にあったものの値をとります'func_1'から)、次の割り当て(' func_2'からの 'A')はそれ以降のバイトになります。 – Iluvatar

+2

名前をAからBに変更しても、「スタックの使用をテストする」ことはできません。 「名前付き変数のプール」のようなものはありません。あなたが何を求めているのか不明です。 – EJP

+1

特定のアーキテクチャがなければ、自動変数のスタックまたはその他の特定のメモリモデルを想定することはできません。そして「プール」はどういう意味ですか?これはこの文脈では意味がありません。名前(識別子)は、それらが識別するオブジェクトの他のプロパティと共にシンボルテーブルにあります。 – Olaf

答えて

3

は、ほとんどの機能func_2();内の変数Aは値40が(func_1()に)保存されたことと同じスタック位置に割り当てられています。 func_2()の変数を初期化していないので、この場合は40のメモリにある変数(これは決して書き換えられなかったため)を使って変数を出力します。これは、ユーザがポインタを解放し、それが見えないかもしれないが、後で競合を見ることができるという主張よりも似ている。未定義の振舞い。言うまでもなく、あなたはそのような行動に頼るべきではありません!

私はそれが名前とは何の関係もないことを証明するために、簡単なテストをした:

void func_1() 
{ 
    int A = 40; 
    int B = 10; 
    printf("Memory A = %p Memory B = %p\n",&A, &B); 
} 

void func_2() 
{ int B; printf("B = %d Memory B = %p\n",B, &B);} 

void main (void) 
{ 
    func_1(); 

    func_2(); 
    printf("\n"); 
} 

出力

Memory A = 0x7fff58f86b5c Memory B = 0x7fff58f86b58 
B = 40 Memory B = 0x7fff58f86b5c 

あなたがfunc_1()B = 10が見ることができるようにfunc_2()印刷値は40でしたか?変数Aのメモリアドレスがfunc_1()であることを確認すると、0x7fff58f86b5cは変数Bが占める同じメモリアドレスがfunc_2()になります。

+0

*は〜ではないはずですか? – GurV

+0

LOL、はい;)それを指摘してくれてありがとう – dreamcrash

3

彼は理解していない振る舞いを説明しているようなアイデアを発明したばかげた役割を果たしています。名前付き変数のプールはありません。

このコードの動作は未定義であり、依存することはできません。実行時に値40を出力するように動作した場合、それは単に実装の事故に過ぎません。

関連する問題