您需要fark
在使用前声明。如第 6.5.2.2 节第 6 段所述:
如果表示被调用函数的表达式的类型不包含原型,则对每个参数执行整数提升,并将具有类型的参数float
提升为double
. 这些被称为默认参数提升。
(我加粗强调)。
请注意,fark
使用与隐式假定类型不兼容的类型进行定义是违反约束的,并且如果调用和定义位于同一翻译单元中,则需要编译器发出诊断消息。gcc 仅在那时发出警告,但 clang 拒绝代码 [ error: conflicting types for 'fark'
]。如果调用和定义在不同的翻译单元中,编译器当然不能诊断错误,但是通过类型不兼容的表达式调用函数无论如何都会调用未定义的行为。
当值0.7f
转换为double
(我假设float
使用 IEEE754 32 位表示和double
IEEE754 64 位表示)时,您会得到一个值
0.699999988079071
其位模式(以十六进制表示)是
0x3FE6666660000000
(偏置指数为 1022,对应 的有效指数,有效指数-1
为1.6666660000000
)。
即在堆栈上或在寄存器中传递给fark
.
当fark
从该表示中读取 32 位时 - 因为它期望float
根据其定义 - 根据double
传递的方式,它可能会读取高阶 32 位或低阶 32。
在这种情况下,它确实读取了低 32 位,从而产生了float
具有位模式的值
0x60000000
它有一个有偏指数0xC0 = 192
, 对应于无偏指数192 - 127 = 65
和 有效数1.000000
. 换句话说,这float
就是
2^65 = 36893488147419103232
这是打印的值。