0

コードは次のとおりです。

#include <stdio.h>

int *addition(int a, int b);

int result;
int *result_ptr;

int *addition(int a, int b)
{
    int c = a + b;
    int *d = &c;

    return d;
}

int main(void)
{
    result = *(addition(1,2));  
    result_ptr = addition(1,2);

    printf("result = %d\n", result); //outputline1
    printf("result_ptr = %d\n", *result_ptr); //outputline2

    return 0;
}

現在のコードが書かれているようにコンパイルされて処理されると、result_ptr は奇妙な値を返します。ただし、2 つの出力行を入れ替えると、そうはなりません。なぜそれをするのですか?

4

1 に答える 1

2

ローカル変数のアドレスを返していますc。これは未定義の動作です。つまり、あなたのプログラムには誤りがあり、これは、予測可能な、または正常な動作を示す義務がないことを意味します。2 つの位置を変更すると、printf別の誤ったプログラムが作成されますが、これは (再び) 正しく動作するか、以前の誤ったプログラムと一貫して動作する必要はありません。

編集(C99 ドラフト標準 N1256 から関連する引用を追加 - 強調鉱山)

6.5.3.2 アドレスおよび間接演算子

[...]

セマンティクス

単項 * 演算子は間接指示を表します。オペランドが関数を指している場合、結果は関数指定子になります。オブジェクトを指している場合、結果はオブジェクトを指定する左辺値です。オペランドの型が「型へのポインター」の場合、結果の型は「型」になります。ポインターに無効な値が割り当てられている場合、単項 * 演算子の動作は未定義です。87)

(脚注 #87)

したがって、は (がヌル ポインターであっても) およびと&*E同等です。E が関数指定子または単項演算子の有効なオペランドである左辺値である場合、は関数指定子または に等しい左辺値であることが常に真です。が左辺値で、がオブジェクト ポインター型の名前である場合、は、指すものと互換性のある型を持つ左辺値です。EE&(E1[E2])((E1)+(E2))&*&EE*PT*(T)PT

単項演算子によるポインターの逆参照の無効な値に*は、null ポインター、指すオブジェクトの型に対して不適切にアラインされたアドレス、およびオブジェクトの有効期間が終了した後のアドレスがあります。

関連する文は最後の文です (強調は私のものです):ローカル変数は、関数cによって返されたそのアドレスが.additionmain

于 2013-09-14T11:07:35.907 に答える