40
#include <stdio.h>

int foo1(void)
{
    int p;
    p = 99;
    return p;
}

char *foo2(void)
{
    char buffer[] = "test_123";
    return buffer;
}

int *foo3(void)
{
    int t[3] = {1,2,3};
    return t;
}

int main(void)
{
    int *p;
    char *s;

    printf("foo1: %d\n", foo1());
    printf("foo2: %s\n", foo2());
    printf("foo3: %d, %d, %d\n", p[0], p[1], p[2]);
    return 0;
}

これをgcc -ansi -pedantic -W -Wallコンパイラーでコンパイルすると、foo2()およびfoo3()に対して警告メッセージが発行されます。

warning: function returns address of local variable

ローカル変数を返すことは許可されていないと思いましたが、foo1()は正常に機能し、ローカルオブジェクトへのポインターを返すこととオブジェクト自体に大きな違いがあるようです。

誰かがこの問題に光を当てることができますか?前もって感謝します!

4

4 に答える 4

32

ここでの問題は、ローカル変数を作成すると、スタックに割り当てられるため、関数の実行が終了すると使用できなくなることです(実装はここで異なります)。望ましい方法は、malloc()非ローカルメモリを予約するために使用することです。ここでの危険は、をfree()使用して割り当てたすべての割り当てを解除する必要があるmalloc()ことです。忘れると、メモリリークが発生します。

于 2011-01-28T02:49:08.707 に答える
25

の場合、ローカル変数自体ではなく、ローカル変数のコピーfoo1()を返します。

他の関数の場合は、ローカル変数へのポインターのコピーを返します。ただし、そのローカル変数は関数の終了時に割り当てが解除されるため、後で参照しようとすると厄介な問題が発生します。

于 2011-01-28T02:48:44.120 に答える
6

どの変数もメモリ内にいくらかのスペースがあります。ポインタはそのスペースを参照します。ローカル変数が占めるスペースは、関数呼び出しが戻るときに割り当てが解除されます。つまり、他の目的で再利用でき、再利用されます。結果として、その空間への言及は、完全に無関係な何かを指し示すことになります。Cの配列はポインターとして実装されているため、最終的にはそれらに適用されます。また、関数で宣言された定数配列もローカルとしてカウントされます。

配列またはそれが作成された関数の範囲を超えて他のポインターを使用する場合は、mallocを使用してそのスペースを予約する必要があります。mallocを使用して予約されたスペースは、freeを呼び出して明示的に解放されるまで、再割り当てまたは再利用されません。

于 2011-01-28T02:46:11.973 に答える
0

はい、実際には舞台裏のポインタである配列を、初期化した変数の内容が格納されているメモリ位置のアドレスに返しています。したがって、実際には配列値の1つを意味する場合は、そのような結果を返すことはそれほど有用ではない可能性があることを警告しています。

于 2011-01-28T02:49:12.053 に答える