2012-07-27 102 views
0
#include<stdio.h> 

int *fun(); 
int main()  
{ 
    int *ptr; 
    ptr=fun(); 
    printf("%d",*ptr); 
    printf("%d",*ptr); 
} 
int * fun() 
{ 
    int k=4;//If auto then cannot print it two times.....stack will be changed 
    return(&k); 
} 

O/P: 4 
    -2 

第一次調用printf()會輸出正確的值。調用堆棧 - 函數返回調用函數的局部變量引用,然後調用另一個函數

調用任何功能(甚至printf()函數)調用的樂趣後,立即()。這一次printf()打印一個垃圾值。爲什麼會發生這種情況?爲什麼我們在第一個打印語句本身期間沒有獲得垃圾值?

回答

1

這不是你可以依賴的行爲;它可能並可能會在不同的系統上有所不同,甚至不同版本的編譯器或不同的編譯器開關。

鑑於這種情況,什麼是可能發生的事情是這樣的:好玩返回一個指向它存儲ķ。堆棧的這部分不再可靠,因爲分配它的函數已經退出。儘管如此,還沒有人寫過它,所以4仍然是寫在它的地方。然後主要準備調用printf。爲此,它獲得第一個參數* ptr。要做到這一點,它從地方ptr點,這是k的(前)地址加載,所以負載得到4那裏。這4存儲在寄存器或棧位置以傳遞給printf。然後格式字符串「%d」的地址被存儲以傳遞給printf。然後printf被調用。在這一點上,printf使用了大量的堆棧,並在k中使用了新的數據。然而,作爲參數傳遞的4是在一個安全的地方,printf的參數應該是這樣,所以printf會打印它。然後printf返回。然後主程序準備再次調用printf。這一次,當它從ptr點加載時,4不再存在;這是在第一次調用printf期間寫入的某些值。所以這個值就是傳遞給printf的東西,就是打印的東西。

不要寫一個使用該行爲的代碼。這是不可靠的,它不是正確的代碼。

0

可變k是本地fun(),意味着它會被銷燬該函數返回時。這是一種非常糟糕的編碼技術,並且總會導致問題。

爲什麼第一printf返回正確值的原因:

,首先它可能會或可能不會返回值。假設k寫在堆棧內存的某處。當函數返回printf時,第一次可能會得到正確的值,因爲那部分內存可能存在一段時間。但這並不能保證。

1

爲什麼它讓你感到驚訝?行爲是不確定的,但觀察你觀察到的事物並沒有什麼不尋常的。

所有變量都生活在內存中的某個地方。當一個變量被正式銷燬時(就像函數退出時的局部變量一樣),它用來佔用的內存依然存在,而且很可能仍然保存着寫入它的最後一個值。這個內存現在正式免費,但它將繼續保持最後的值,直到其他代碼重用該內存用於其他目的並覆蓋它。

這是你在實驗中觀察到的東西。即使變量k不再存在,指針ptr仍然指向其以前的位置。而且前一個位置仍然恰好保留了k的最後一個值,即4

的第一個printf「成功」接收值的副本進行打印。而第一個printf實際上是重用舊內存位置並覆蓋前一個值k的那個。所有進一步嘗試解除引用ptr將顯示4不再存在,這就是爲什麼您的第二個printf打印別的東西。

相關問題