看板 C_and_CPP 關於我們 聯絡資訊
開發平台(Platform): (Ex: Win10, Linux, ...) win 10 用cygwin64 64位元 編譯器(Ex: GCC, clang, VC++...)+目標環境(跟開發平台不同的話需列出) GCC 額外使用到的函數庫(Library Used): (Ex: OpenGL, ...) no 問題(Question): 簡單的printf問題 int a = 10; printf( "%f\n", a ); float w = 35.14; printf( "%w d\n", w ); 餵入的資料(Input): 沒有 預期的正確結果(Expected Output): 預期第一個printf輸出的是10.0 當然結果大家知道是0 想請問為甚麼這個型態錯誤印出的是0 ? 原本想說都是佔4bytes應該會誤打誤撞可以顯示好 爬到英文說跟甚麼IEEE有關?英文看不是很懂.... 再來既然格式都一樣錯誤 為甚麼第二個printf有印出東西但是是亂數,這個數是其他記憶體空間裡的數字嗎? 錯誤結果(Wrong Output): 0 ( undefined? ) 1073741824 ( 亂數 ) 程式碼(Code):(請善用置底文網頁, 記得排版) 補充說明(Supplement): -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 42.72.57.150 ※ 文章網址: https://www.ptt.cc/bbs/C_and_CPP/M.1509042559.A.2EE.html
LPH66: 這問題會牽涉到不少這些 C 語言功能的實作細節10/27 02:34
LPH66: 要完整回答會很長一串, 但一般寫程式不需要考慮這些細節10/27 02:35
kingofsdtw: google吧 :D10/27 02:35
Schottky: 我覺得不好,我覺得這樣寫程式很危險,把 -Wall 打開吧10/27 02:41
hpyhacking: 這是故意的 10/27 02:44
a58524andy: 先讀計概10/27 06:00
peterwu4: 可以查一下float和int儲存格式的差異~ 啊,你已經查了XD10/27 07:42
peterwu4: 找中文的網頁說明來看~10/27 07:42
peterwu4: 0的部分比較好解釋,因為浮點數小點的部分都是放在格式10/27 07:52
peterwu4: 後面,整數的10,32bit的格式,後三個byte都是0,所以小10/27 07:53
peterwu4: 數點的部分是零,乘什麼都結果都是零。同理去理解另一個10/27 07:55
peterwu4: 部分吧~10/27 07:55
peterwu4: 浮點數存的時候4個byte裡都有東西,用整數讀出來當然就10/27 07:57
peterwu4: 是怪怪的數字了10/27 07:57
vm0: 我實際在linux上用gcc跑,printf("%d\n",w)會是35,跟印象中一10/27 10:17
vm0: 樣,在宣告時就會自動省略小數,請教是為什麼呢?10/27 10:18
nh60211as: 他要打double w = 35.14打錯了吧10/27 10:22
vm0: 原來如此,看前幾樓回的還以為我哪裡搞錯了,謝謝10/27 10:41
nh60211as: 我也不確定,照他的錯誤結果輸入應該是浮點數才對10/27 10:56
MOONRAKER: printf不依照格式字串檢查變數格式。有錯誤結果自負。10/27 11:08
hpyhacking: 先謝謝大家一聲,還有我現在就是在讀計概QQ10/27 12:07
※ 編輯: hpyhacking (42.72.57.150), 10/27/2017 12:15:03
hpyhacking: 不好意思有打錯的!!! 10/27 12:15
※ 編輯: hpyhacking (42.72.57.150), 10/27/2017 12:17:13
Schottky: 假如 printf 期望的 size 和變數 size 不一樣會出大事 10/27 13:38
ersfw4418: IEEE754 10/27 16:47
yvb: 若是要 "正確的" 把 double "誤" 當做 int 來印, 應該寫做 10/27 20:42
yvb: printf("%d\n", *(int *)&w); 結果 35.14 會是 -2061584302 10/27 20:42
yvb: 而原 PO 的 printf("%d\n", w); 在 Linux 系統開了 ASLR 時, 10/27 20:43
yvb: 甚至每次顯示結果都不同, 真的像是亂數一般. 顯然是 va_list 10/27 20:43
yvb: 這個黑盒子中不知發生了什麼事. 10/27 20:43
akasan: ABI 10/27 20:48
AstralBrain: 以 amd64 來說, 浮點數 w 會進 xmm0 register 10/27 21:30
AstralBrain: 然後 printf 從沒使用的 rdi 讀一個整數, 所以是什麼 10/27 21:31
AstralBrain: 值都有可能 10/27 21:31
PkmX: 樓上rdi應該是format string 所以下一個參數是rsi 10/28 15:45
AstralBrain: 啊對... 忘了有 format string 10/29 06:08
LPH66: 這裡還要考慮可變參數, 我其實不太確定 amd64 的可變參數 10/29 09:13
LPH66: 會不會用到浮點數暫存器... 10/29 09:13
LPH66: 我所知的可變參數實作幾乎都是全部推堆疊 10/29 09:13
LPH66: 噢, 找到資料了, 即使是可變參數 amd64 一樣會用暫存器 10/29 09:21
LPH66: 那用了多少 xmm 暫存器傳浮點數會以 al 傳進去 10/29 09:23
LPH66: 所以就是上面 Astral 講的那個樣子 10/29 09:23
yvb: 其實我前面只是要指出, 原PO 的問題, 在 X86-64 的環境下, 10/30 00:46
yvb: 並非單純是 IEEE754 的問題, 照規則算出 "亂數" 會不符合; 10/30 00:47
yvb: 當然, 若是在 i386 (32-bit) 的環境, 應該就會回歸單純了. 10/30 00:47
yvb: 另外, 上面 regs 的推論, 會讓人覺得在瞎子摸象, 可參考 10/30 00:47
yvb: (1) http://goo.gl/yP27aR 及 (2) http://goo.gl/WPLhd9 10/30 00:48
yvb: 此外, 依據 (1) 及其後 List 的 X86-64 段落, 我的測試使用 10/30 00:48
yvb: Linux => System V AMD64 ABI, 但原PO 則為 Win10 cygwin64, 10/30 00:48
yvb: 不知是會採用 SysV 還是 M$ X64 calling convention ? 10/30 00:48
yvb: 有關 regs 的相關推論, 不知是否依舊完全符合? 10/30 00:49
hpyhacking: 今天期中考完我再來研究一下 11/10 17:53