當我試圖運行編譯並在一個簡單的C文件來執行這個語句:惠普這個程序的輸出是什麼?
main(){ printf("%d");}
它是給我64和AIX上的給我804359524.
誰能告訴我什麼是這種行爲。
當我試圖運行編譯並在一個簡單的C文件來執行這個語句:惠普這個程序的輸出是什麼?
main(){ printf("%d");}
它是給我64和AIX上的給我804359524.
誰能告訴我什麼是這種行爲。
我假定你的意思:
int main()
{
printf("%d");
}
既然如此,printf()的被讀取int從棧(由格式說明%d的方向)。既然你沒有指定一個,它只是讀取堆棧中的任何內容並使用它。因此,你看到僞隨機輸出。
相反,嘗試:
int main()
{
printf("%d", 10101);
}
HTH
代碼暴露了未定義的行爲。在其他系統上,它可能會打印「堆棧溢出」(嚴重!)。 %d告訴CRT庫你會提供一個整數,但是你沒有。
我不認爲你會在代碼中遇到堆棧溢出 - 堆棧不會增長。 – Skizz 2009-10-07 10:20:10
堆棧溢出的觸發器通常是對堆棧保護頁面的內存訪問。當printf()無法讀取%d整數時,可能會觸發該訪問,而是碰到守護頁。由於這不是一個寫,你不能通過添加另一個頁面來解決它。每當有任何不可修復的堆棧守衛頁面違例時,操作系統打印「堆棧溢出」是合理的;它會是99%正確的 – MSalters 2009-10-07 11:17:43
我認爲在這種情況下,打印的值將是printf函數的返回地址,寄存器值或可能來自main的堆棧幀,具體取決於編譯器的實現和它正在運行的操作系統。我一直認爲'堆棧溢出'是當堆棧嘗試將數據存儲在堆棧時內存不足時,從不讀取數據時。 – Skizz 2009-10-07 12:06:53
我的猜測是,你編譯
main(){ printf("%d");}
這將摘掉當前堆棧的隨機值。試試這個:
main() {
printf("%d", 0);
printf("%d");
}
現在,第二printf()
將始終打印0
,因爲它得到了相同的堆棧的第一個電話。
[編輯]這不適用於x86 Linux與GCC 4.1.2。下面是所生成的彙編程序代碼(使用gcc -S -o t.s t.c
):
movl $0, %esi
movl $.LC0, %edi
movl $0, %eax
call printf
movl $.LC0, %edi
movl $0, %eax
call printf
正如你可以看到,第二個參數是不是壓入堆棧,但通過經由%esi
(這是一個寄存器)。同一個寄存器可能在printf()
中被修改,這就是它失去其價值的原因。該死的優化;)
這是經典undefined behavior。編譯器不檢查你是否提供了足夠的參數來匹配你的格式化字符串。有編譯器這樣做(gcc is one),但你的不。
在printf()
的代碼將通過它的給定的格式化串愉快步驟,並且當它到達「%d」,它將讀出一個尺度的int
參數(通常爲:從電池堆),不知道沒有參數在那裏讀取。
無論堆棧上發生什麼值,都會打印出來。
有些編譯器,如gcc,如果指定了足夠高的警告級別,就會遇到這種類型的常見問題。像這樣(編譯你的代碼,用-Wall - 所有的警告):
gcc -c -g -Wall -MMD -MP -MF build/Debug/Cygwin-Windows/newmain.o.d -o build/Debug/Cygwin-Windows/newmain.o newmain.c
newmain.c: In function `main':
newmain.c:16: warning: too few arguments for format
這是大約998很好的理由總是與高警告級別編譯,並認真對待的警告信息之一。
哪種說法? – 2009-10-07 10:07:28
RTFM。 [需要xtra字符] – spender 2009-10-07 10:10:53