[問題] printf 格式不同問題(修正)

看板C_and_CPP作者 (駭人聽聞)時間7年前發表 (2017/10/26 18:29), 7年前編輯推噓12(12039)
留言51則, 14人參與, 7年前最新討論串1/1
開發平台(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

10/27 02:34, 7年前 , 1F
這問題會牽涉到不少這些 C 語言功能的實作細節
10/27 02:34, 1F

10/27 02:35, 7年前 , 2F
要完整回答會很長一串, 但一般寫程式不需要考慮這些細節
10/27 02:35, 2F

10/27 02:35, 7年前 , 3F
google吧 :D
10/27 02:35, 3F

10/27 02:41, 7年前 , 4F
我覺得不好,我覺得這樣寫程式很危險,把 -Wall 打開吧
10/27 02:41, 4F

10/27 02:44, 7年前 , 5F
這是故意的
10/27 02:44, 5F

10/27 06:00, 7年前 , 6F
先讀計概
10/27 06:00, 6F

10/27 07:42, 7年前 , 7F
可以查一下float和int儲存格式的差異~ 啊,你已經查了XD
10/27 07:42, 7F

10/27 07:42, 7年前 , 8F
找中文的網頁說明來看~
10/27 07:42, 8F

10/27 07:52, 7年前 , 9F
0的部分比較好解釋,因為浮點數小點的部分都是放在格式
10/27 07:52, 9F

10/27 07:53, 7年前 , 10F
後面,整數的10,32bit的格式,後三個byte都是0,所以小
10/27 07:53, 10F

10/27 07:55, 7年前 , 11F
數點的部分是零,乘什麼都結果都是零。同理去理解另一個
10/27 07:55, 11F

10/27 07:55, 7年前 , 12F
部分吧~
10/27 07:55, 12F

10/27 07:57, 7年前 , 13F
浮點數存的時候4個byte裡都有東西,用整數讀出來當然就
10/27 07:57, 13F

10/27 07:57, 7年前 , 14F
是怪怪的數字了
10/27 07:57, 14F

10/27 10:17, 7年前 , 15F
我實際在linux上用gcc跑,printf("%d\n",w)會是35,跟印象中一
10/27 10:17, 15F

10/27 10:18, 7年前 , 16F
樣,在宣告時就會自動省略小數,請教是為什麼呢?
10/27 10:18, 16F

10/27 10:22, 7年前 , 17F
他要打double w = 35.14打錯了吧
10/27 10:22, 17F

10/27 10:41, 7年前 , 18F
原來如此,看前幾樓回的還以為我哪裡搞錯了,謝謝
10/27 10:41, 18F

10/27 10:56, 7年前 , 19F
我也不確定,照他的錯誤結果輸入應該是浮點數才對
10/27 10:56, 19F

10/27 11:08, 7年前 , 20F
printf不依照格式字串檢查變數格式。有錯誤結果自負。
10/27 11:08, 20F

10/27 12:07, 7年前 , 21F
先謝謝大家一聲,還有我現在就是在讀計概QQ
10/27 12:07, 21F
※ 編輯: hpyhacking (42.72.57.150), 10/27/2017 12:15:03

10/27 12:15, 7年前 , 22F
不好意思有打錯的!!!
10/27 12:15, 22F
※ 編輯: hpyhacking (42.72.57.150), 10/27/2017 12:17:13

10/27 13:38, 7年前 , 23F
假如 printf 期望的 size 和變數 size 不一樣會出大事
10/27 13:38, 23F

10/27 16:47, 7年前 , 24F
IEEE754
10/27 16:47, 24F

10/27 20:42, 7年前 , 25F
若是要 "正確的" 把 double "誤" 當做 int 來印, 應該寫做
10/27 20:42, 25F

10/27 20:42, 7年前 , 26F
printf("%d\n", *(int *)&w); 結果 35.14 會是 -2061584302
10/27 20:42, 26F

10/27 20:43, 7年前 , 27F
而原 PO 的 printf("%d\n", w); 在 Linux 系統開了 ASLR 時,
10/27 20:43, 27F

10/27 20:43, 7年前 , 28F
甚至每次顯示結果都不同, 真的像是亂數一般. 顯然是 va_list
10/27 20:43, 28F

10/27 20:43, 7年前 , 29F
這個黑盒子中不知發生了什麼事.
10/27 20:43, 29F

10/27 20:48, 7年前 , 30F
ABI
10/27 20:48, 30F

10/27 21:30, 7年前 , 31F
以 amd64 來說, 浮點數 w 會進 xmm0 register
10/27 21:30, 31F

10/27 21:31, 7年前 , 32F
然後 printf 從沒使用的 rdi 讀一個整數, 所以是什麼
10/27 21:31, 32F

10/27 21:31, 7年前 , 33F
值都有可能
10/27 21:31, 33F

10/28 15:45, 7年前 , 34F
樓上rdi應該是format string 所以下一個參數是rsi
10/28 15:45, 34F

10/29 06:08, 7年前 , 35F
啊對... 忘了有 format string
10/29 06:08, 35F

10/29 09:13, 7年前 , 36F
這裡還要考慮可變參數, 我其實不太確定 amd64 的可變參數
10/29 09:13, 36F

10/29 09:13, 7年前 , 37F
會不會用到浮點數暫存器...
10/29 09:13, 37F

10/29 09:13, 7年前 , 38F
我所知的可變參數實作幾乎都是全部推堆疊
10/29 09:13, 38F

10/29 09:21, 7年前 , 39F
噢, 找到資料了, 即使是可變參數 amd64 一樣會用暫存器
10/29 09:21, 39F

10/29 09:23, 7年前 , 40F
那用了多少 xmm 暫存器傳浮點數會以 al 傳進去
10/29 09:23, 40F

10/29 09:23, 7年前 , 41F
所以就是上面 Astral 講的那個樣子
10/29 09:23, 41F

10/30 00:46, 7年前 , 42F
其實我前面只是要指出, 原PO 的問題, 在 X86-64 的環境下,
10/30 00:46, 42F

10/30 00:47, 7年前 , 43F
並非單純是 IEEE754 的問題, 照規則算出 "亂數" 會不符合;
10/30 00:47, 43F

10/30 00:47, 7年前 , 44F
當然, 若是在 i386 (32-bit) 的環境, 應該就會回歸單純了.
10/30 00:47, 44F

10/30 00:47, 7年前 , 45F
另外, 上面 regs 的推論, 會讓人覺得在瞎子摸象, 可參考
10/30 00:47, 45F

10/30 00:48, 7年前 , 46F
10/30 00:48, 46F

10/30 00:48, 7年前 , 47F
此外, 依據 (1) 及其後 List 的 X86-64 段落, 我的測試使用
10/30 00:48, 47F

10/30 00:48, 7年前 , 48F
Linux => System V AMD64 ABI, 但原PO 則為 Win10 cygwin64,
10/30 00:48, 48F

10/30 00:48, 7年前 , 49F
不知是會採用 SysV 還是 M$ X64 calling convention ?
10/30 00:48, 49F

10/30 00:49, 7年前 , 50F
有關 regs 的相關推論, 不知是否依舊完全符合?
10/30 00:49, 50F

11/10 17:53, 7年前 , 51F
今天期中考完我再來研究一下
11/10 17:53, 51F
文章代碼(AID): #1PyYb_Bk (C_and_CPP)