2017-06-19 7 views
0

これら2例についてはされて私の質問:C - ローカル変数の対ローカルポインタを返す

#include <stdio.h> 
int *foo1(); 
int *foo2(); 

int main() 
{ 
    printf("so it's %d\n",*foo1()); 
    printf("so it's %d\n",*foo2()); 
} 

int *foo1() 
{ 
    int i1 = 5; 
    return &i1; 
} 

int *foo2() 
{ 
    int i2 = 5; 
    int *p = NULL; 
    p = &i2; 
    return p; 
} 

ケース1: foo1は()との場合は、我々は返すようにしようとしているため、エラーを取得するとその主なデータへのアドレスのコピーが削除されている(私たちは、foo1は()関数を終了したとき)

事例2:しかし、foo2は()で、それは、私たちがコピーを返却しているかかわらず、エラーを与えるものではありませんデータが削除されるローカル変数のポインタd foo2()関数を終了した後、なぜそうですか?

TL:DR:なぜfoo2()はエラーを出さないがfoo1()はなぜですか?

TIA。

+0

CまたはC++へのポインタを返すことはできません。また、g ++、[両方に警告を与える](http://coliru.stacked-crooked.com/a/5ee45849a93cd26d) – NathanOliver

+0

私は、* foo1 *がrvalueを返す間に* foo2 *はlvalueを返しています。これはポインタアドレス自体が無効であっても有効な戻り値です。 – abe

+0

なぜダブルタグですか? – StoryTeller

答えて

8

両方の関数の動作がとfoo2の場合、は未定義です(CとC++の両方)。

逆参照範囲外の自動保存期間を持つ変数を指すポインタ。

明日、foo2()でもエラーが表示される場合があります。コンパイラがあなたの猫を食べるかもしれない。

+0

便利な答え - 私は私の猫がコンパイラによって食べられないように常に私のコードを3回チェックしています。 – Peri461

+0

私もそうです。私の猫を研究から除外しました。 – Bathsheba

+0

コンパイラが猫を食べるようなコーディングを避けるべきです。 :O –

1

どちらの場合でも、ローカル変数へのポインタを返して逆参照することによってundefined behaviorを呼び出しています。

未定義の動作を呼び出すことは、常にクラッシュするという意味ではありません。これは、プログラムの動作が定義されていないことを意味します。クラッシュしたり、奇妙な結果を出力したり、正しく動作するように見える可能性があります。ご覧のとおり、この動作は、プログラムのこれらの2つの方法で明らかになります。

未使用のローカル変数やデバッグ用のprintfの追加など、一見無関係な変更を加えると、未定義の動作がどのように表示されるかを変更できます。

1

どちらも未定義の動作です。コンパイラに依存して、未定義の動作を警告することはできません。

あなたは本質的に両方の機能で同じことをしていますが、実際には両方とも同じアセンブリコードが生成される可能性があります。

1

case1とcase2の両方の動作が定義されていないため、ローカル変数

関連する問題