2014-02-11 61 views
-1

我寫了下面的程序:呼叫的printf(「%d」)兩次,常量導致

#include<stdio.h> 

int main(){ 
     printf("%x\n"); 
     printf("%x\n"); 
     return 0; 
} 

我知道這是不確定的行爲,我只是檢查會發生什麼。編譯器是gcc。

樣本輸出是:

541d3118 
7ffffff7 

另一個樣本輸出是:

e0b08078 
7ffffff7 

當我與-O3標誌編譯它,結果是:

5ec20f18 
9 

而且

3bedfa08 
9 

爲什麼第一個值會改變,但不是第二個值?爲什麼第二個值在高優化級別上有所不同?

+3

未定義的行爲:您需要向'printf'添加一個int變量。 –

+0

我想要一個選項來關閉帶有「未定義行爲」的問題作爲原因。 – DevSolar

+1

@DevSolar爲什麼?試圖理解代碼如何以這種方式工作可能是完全合法的。 – glglgl

回答

3

我會盡量從學術的角度來看你的問題。正如你所看到的,你得到的東西是不可靠的(一如未定義的行爲一樣),你永遠不應該依賴它。

但afaict你有興趣知道你爲什麼看到你所看到的。

實質上,調用一個函數並將參數傳遞給它通過堆棧工作。 (這僅保存了一些架構,不是所有)。

A「正常通話」這個功能,那麼可能看起來像

push argument 2 
push argument 1 
call 

如果要調用它作爲

push argument 1 
call 

的函數將第二個參數看作完全不同的東西, G。調用函數的返回地址或局部變量,或當前在堆棧上的其他任何內容。

所以這個值取決於先前在堆棧上的內容,甚至可能包含了作爲局部變量和其他情況的內容。

而且,當然,它也可以取決於所選擇的優化級別,因爲它可以控制哪些變量首先放在堆棧上。

這就是爲什麼你不應該這樣做的原因:你有絕對不能控制你在這裏得到什麼。

5

你打電話printf沒有指定一個值,其中有格式說明符%x。這會調用未定義的行爲,所以您觀察到的可能是編譯器的巧合或特定實現。無論哪種方式調用未定義的行爲在你的代碼中都不是好事。

2

printf的調用中,根據標準,「如果格式參數不足,行爲未定義」。你目睹了這種行爲。