6

C でスタック フレームを理解しようとしているので、スタック フレームを分析する簡単な C コードを書きました。

  • まず最初に、fun1() は 10 に初期化されたローカル変数のアドレスを ptr に返しますが、これは警告につながりますが、それは問題ありません... *ptr の値を出力すると、10 が出力されますが、それでも問題ありません.. .

  • 次の fun2() は、初期化さえされていないローカル変数のアドレスを返します。 *ptr の値を出力しようとすると、a または b のアドレスを返すかどうかに関係なく、10 が出力されます...

  • ここで実際に何が起こっているのかを理解するために、gdb を利用しました。gdb を使用して、段階的なデバッグを開始し、fun2()の「 return &a 」の行に到達したとき、b のアドレスを出力しようとしましたが 、 &bを出力しようとしましたが、 Can't take address of "b" which is not を出力しました左辺値。

a のアドレスを出力しようとすると、 &aを出力するとまったく問題なく出力されるのに、なぜ b のアドレスが出力されないのかわかりません。* a が左辺値であるのに b が左辺値でないのはなぜですか?

# include <stdio.h>

int * fun1() {
    int a = 10; 
    return &a; 
}

int * fun2()
{
    int a;
    int b;
    return &a;           // return &b;
}

int main ()  
{
    int *ptr;
    ptr = fun1();
    ptr = fun2();
    printf ("*ptr = %d, fun2() called...\n", *ptr);
    return 0;
}
4

2 に答える 2

3

コンパイラは の一部のコードを最適化していますfun2

戻る場合&aは、最適化を行っていint b;ます。戻る場合&bは、最適化を行っていint a;ます。ダミーの計算を追加すると、返される値のアドレスが異なることがわかります。

int * fun2()
{
    int a;
    int b;
    int* p = &a;
    p = &b;
    return p;
}

mainの戻り値を出力するように変更します。fun1fun2

int main ()  
{
    int *ptr;
    ptr = fun1();
    printf ("ptr = %p, fun1() called...\n", ptr);
    ptr = fun2();
    printf ("ptr = %p, fun2() called...\n", ptr);
    printf ("*ptr = %d, fun2() called...\n", *ptr);
    return 0;
}

このコードを実行すると、次のサンプル出力が得られます。

ptr = 0x7ffff98c70ec、fun1() が呼び出されました...
ptr = 0x7ffff98c70e4、fun2() が呼び出されました...
*ptr = 32749、fun2() が呼び出されました...
于 2014-04-25T05:40:39.407 に答える
0

アドレスをbに返すと、うまくコンパイルされます。ただし、ローカル変数のアドレスを返すことは想定されていません。 このリンクをチェックしてください

于 2014-04-25T05:36:01.913 に答える