作者djshen (djshen)
看板C_and_CPP
标题Re: 关於c++的输出问题
时间Fri Jun 28 23:37:19 2019
※ 引述《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://webptt.com/cn.aspx?n=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://webptt.com/cn.aspx?n=bbs/C_and_CPP/M.1561736243.A.C6D.html
1F:推 LPH66: 问题就在於 amd64 ABI 会要求一些能放暂存器的参数要放过去 06/29 00:18
2F:→ LPH66: 这里只有一个指标和一个浮点数, 应该是够用的 06/29 00:18
3F:→ LPH66: 但 MSVC 不知为什麽依然全部丢堆叠 06/29 00:18
4F:→ LPH66: 我是猜测不知道哪里的设定不一样使得 MSVC 做这样设定 06/29 00:20
5F:→ LPH66: 话说刚刚突然想到一个可能原因: 或许 MSVC 的预设设定是 06/29 00:22
6F:→ LPH66: 编出 32-bit 程式, 所以才是使用堆叠 06/29 00:23
7F:→ djshen: 看起来应该是这样 compiler改成x64 msvc就会用register了 06/29 00:36
8F:推 wei115: 话说在msys2上的gcc跑也会是0,用-m64(-m32错误) 06/29 02:12
9F:→ wei115: 照上面的思路,gcc应该也是把东西都堆叠(就算x64) 06/29 02:13
10F:→ wei115: 那gcc为什麽没把东西都register? 06/29 02:13
11F:→ wei115: 都->丢 06/29 02:15
12F:推 ac01965159: 感谢大大的解惑。 07/01 14:52