2017-06-19 77 views
0

我的問題是關於這兩種情況下:Ç - 返回本地指針VS局部變量

#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 *返回一個右值而* foo2 *返回一個左值,即使指針地址本身無效,該值也是有效的返回值。 – abe

+0

爲什麼是雙標籤? – StoryTeller

回答

8

在C和C++中,函數foo1foo2的行爲都是undefined

您不允許使用解除引用指向指向自動存儲持續時間不在範圍內的變量的指針。

明天,foo2()也可能會給你一個錯誤。或者編譯器可能會吃掉你的貓。

+0

有用的答案 - 我總是三重檢查我的代碼,以確保我的貓不會被編譯器吃掉。 – Peri461

+0

我也是;從研究中刪除了我的貓。 – Bathsheba

+0

我們當然應該避免編碼做法,導致編譯器吃貓! :O –

1

在這兩種情況下,您都會調用undefined behavior,方法是返回一個指向局部變量的指針並對其進行解引用。

調用未定義的行爲並不意味着您將始終崩潰。這意味着程序的行爲是不確定的。它可能會崩潰,它可能會輸出奇怪的結果,或者它可能看起來正常工作。正如你所看到的,這種行爲在你的程序中以兩種方式體現出來。

做出看似無關的更改(如添加未使用的局部變量或用於調試)可以改變未定義行爲的體現方式。

1

兩者都是未定義的行爲,您不能依賴編譯器給出未定義行爲的警告。

你基本上在兩個函數中都做了同樣的事情,實際上兩者都可能導致生成相同的彙編代碼。

1

兩個案例1和情況2是不確定的行爲,你不能返回指向局部變量