Re: 關於c++的輸出問題

看板C_and_CPP (C/C++)作者 (djshen)時間6年前 (2019/06/28 23:37), 編輯推噓3(309)
留言12則, 4人參與, 6年前最新討論串2/2 (看更多)
※ 引述《ac01965159 (leeleo)》之銘言: : 標題: 關於c++的輸出問題 : 時間: Thu Jun 27 10:49:32 2019 : : https://i.imgur.com/Qmnd7YW.jpg
: 上圖是我的測試,上網查過資料後,我的認知是編譯器在即將把float格式輸出前,會先 : 轉成double的格式,而%d會取低32bit的值轉10進制再拿去輸出,我把我的輸出值0.5手 : 動轉成double後,發現取低32bit的輸出應是0才對,但是結果如圖卻不是,所以想請教 : 各位是我哪裡理解錯了嗎? : 謝謝。 : : : -- : ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 124.9.128.30 (臺灣) : ※ 文章網址: https://www.ptt.cc/bbs/C_and_CPP/M.1561603774.A.126.html : 推 LPH66: 我猜它拿到垃圾值了 06/27 11:25 : → LPH66: 我是指 printf; 不過為什麼會有垃圾值一下子想不到可能原因 06/27 11:26 : → djshen: %d不是int? 06/27 11:59 : → james732: 我在MSVC是得到0,但gcc每次結果都不同 XD 06/27 12:12 : → james732: https://i.imgur.com/3FwFQ4A.png
06/27 12:14 : → james732: https://i.imgur.com/wPx5YdM.png
06/27 12:14 : 推 Fenikso: 因為x64的parameter是先放進register不是stack 06/27 12:36 : 推 LPH66: vararg 也會進 reg 嗎? 06/27 12:37 : 推 LPH66: 查了一下資料, 看起來原因應該是浮點數是放在浮點數暫存器 06/27 12:46 : → LPH66: 但 %d 要抓整數所以 printf 嘗試從整數暫存器找資料 06/27 12:46 : → LPH66: 就找到垃圾值了 06/27 12:47 : → LPH66: 然後就找到的東西看起來 vararg 的呼叫端處理沒什麼不同 06/27 12:47 : → LPH66: 所以該 (照 ABI) 進暫存器的就會進去的樣子 06/27 12:48 : → LPH66: 至於 MSVC 都會是 0 就不確定是不是編譯選項的問題了... 06/27 12:49 MSVC的情況 https://godbolt.org/z/CkJrN7 從asm的結果來看 float 0x3FFFFFFF 會先轉成 double 0x3FFFFFFF E0000000 到asm line 10的時候 stack應該會長這樣 __________ addr+0 push %ebp (line 31) __________ addr-4 push %ecx (line 33) __________ addr-8 a.y converted to double addr-12 (line 37) __________ addr-16 push 1 (line 38) __________ addr-20 push %ebp (line 5) __________ addr-24 <- %ebp addr-12 這裡大概是因為實際存到 stack 的是 一個 double 和一個 int 造成參數開始的位置算錯 __________ addr-28 __________ addr-32 <- %esp 接著 line 14 從 -4(addr-12) 讀一個 32-bit integer little endian 所以會讀到 0xE0000000 float 0.5 會轉成 double 0x3FE00000 00000000 剛好最後會讀到 0 -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 36.226.15.37 (臺灣) ※ 文章網址: https://www.ptt.cc/bbs/C_and_CPP/M.1561736243.A.C6D.html

06/29 00:18, 6年前 , 1F
問題就在於 amd64 ABI 會要求一些能放暫存器的參數要放過去
06/29 00:18, 1F

06/29 00:18, 6年前 , 2F
這裡只有一個指標和一個浮點數, 應該是夠用的
06/29 00:18, 2F

06/29 00:18, 6年前 , 3F
但 MSVC 不知為什麼依然全部丟堆疊
06/29 00:18, 3F

06/29 00:20, 6年前 , 4F
我是猜測不知道哪裡的設定不一樣使得 MSVC 做這樣設定
06/29 00:20, 4F

06/29 00:22, 6年前 , 5F
話說剛剛突然想到一個可能原因: 或許 MSVC 的預設設定是
06/29 00:22, 5F

06/29 00:23, 6年前 , 6F
編出 32-bit 程式, 所以才是使用堆疊
06/29 00:23, 6F

06/29 00:36, 6年前 , 7F
看起來應該是這樣 compiler改成x64 msvc就會用register了
06/29 00:36, 7F

06/29 02:12, 6年前 , 8F
話說在msys2上的gcc跑也會是0,用-m64(-m32錯誤)
06/29 02:12, 8F

06/29 02:13, 6年前 , 9F
照上面的思路,gcc應該也是把東西都堆疊(就算x64)
06/29 02:13, 9F

06/29 02:13, 6年前 , 10F
那gcc為什麼沒把東西都register?
06/29 02:13, 10F

06/29 02:15, 6年前 , 11F
都->丟
06/29 02:15, 11F

07/01 14:52, 6年前 , 12F
感謝大大的解惑。
07/01 14:52, 12F
文章代碼(AID): #1T5ZGpnj (C_and_CPP)
討論串 (同標題文章)
本文引述了以下文章的的內容:
完整討論串 (本文為第 2 之 2 篇):
文章代碼(AID): #1T5ZGpnj (C_and_CPP)