2016-10-06 78 views
-1
int* getINT() 
{ 
    int y =10; 
    int *x = &y; 
    return x; 
} 
char* getARRAY() 
{ 
    char str[]= "Hai"; 
    return str; 
} 

int Main(void) 
{ 
    char *ptr; 
    int *result; 
    result = getINT(); 
    printf ("%d\n", *result); 
    ptr = getARRAY(); 
    printf("%s", ptr); 
} 

在主函數* result中保留10的值,而ptr具有垃圾值。我的疑問是,爲什麼*海峽失去範圍,而* X不輸範圍返回範圍如果類型是指針,函數的值

+0

都是未定義的行爲,您不應該依賴「工作」功能。 – mch

+0

巧合。 –

回答

1

都是無效的,並且result仍然是10比什麼巧合。 函數中的值只有在函數中存在時,只要您離開函數,它們就不再存在,因爲它們都在函數的當前堆棧幀內的堆棧上分配。如果函數返回,堆棧框架將被刪除,如果您調用另一個函數,空間將被重用。 因此,任何指向函數堆棧上數據的指針在函數之外基本上都是無用的,因爲機會非常高,數據在您嘗試訪問它時會被覆蓋。

+0

謝謝現在我明白了。其實,當我10歲的時候我很困惑。現在我明白這只是一個巧合 – SouthArcot

1

當您返回一個局部變量的地址,該變量超出範圍,並通過該變量使用的內存位置可以用於其他用途重複使用。試圖取消引用這樣一個指針會調用undefined behavior

當你調用未定義行爲,任何事情都有可能發生。您的代碼可能會崩潰,可能會顯示意外的結果,或者它看起來可能正常工作。對代碼做出看似無關的更改(例如添加一個額外的未使用變量或添加/刪除printf)可能會導致此行爲發生更改。

至於什麼是可能發生的事情,當時你在填充主要result,沒有其他的功能還沒有被調用,所以在getINT使用y棧空間還沒有被覆蓋。在下一個語句中,您取消引用該指針以獲得值y。因爲這是在調用任何函數之前完成的,所以y的值尚未被覆蓋,因此您可以獲取該值。

ptr的情況下,可以直接通過該指針printf。調用printf的操作將寫入堆棧並覆蓋之前由strgetARRAY中佔用的內存。

如果您在打印之前添加printf("hello\n");*result您可能不會打印10的值。同樣,如果您將ptr指向的字符串複製到main(不調用另一個函數)的局部變量中,您可能會恢復字符串Hai

雖然如此,你不能依賴這種行爲。某些編譯器可能會選擇在函數返回後清除堆棧中的內容。同樣,更改優化級別可能會導致函數被內聯,因此沒有堆棧更改。這是未定義行爲的所有部分