3

鉴于以下...

void test(){
  float a = 0.7f;
  LOGD("Width %.1f",0.7f);
  LOGD("Width %.1f",a);
  fark(a);
}

void fark(float test){
  LOGD("Width %.1f",test);
}

这输出....

05-18 22:35:25.215: D/Native(8241): 宽度 0.7

05-18 22:35:25.215: D/Native(8241): 宽度 0.7

05-18 22:35:25.215: D/Native(8241): 宽度 36893488147419103232.0

最后一个我错过了什么?

4

1 回答 1

12

您需要fark在使用前声明。如第 6.5.2.2 节第 6 段所述:

如果表示被调用函数的表达式的类型不包含原型,则对每个参数执行整数提升,并将具有类型的参数float提升为double. 这些被称为默认参数提升

(我加粗强调)。

请注意,fark使用与隐式假定类型不兼容的类型进行定义是违反约束的,并且如果调用和定义位于同一翻译单元中,则需要编译器发出诊断消息。gcc 仅在那时发出警告,但 clang 拒绝代码 [ error: conflicting types for 'fark']。如果调用和定义在不同的翻译单元中,编译器当然不能诊断错误,但是通过类型不兼容的表达式调用函数无论如何都会调用未定义的行为。

当值0.7f转换为double(我假设float使用 IEEE754 32 位表示和doubleIEEE754 64 位表示)时,您会得到一个值

0.699999988079071

其位模式(以十六进制表示)是

0x3FE6666660000000

(偏置指数为 1022,对应 的有效指数,有效指数-11.6666660000000)。

即在堆栈上或在寄存器中传递给fark.

fark从该表示中读取 32 位时 - 因为它期望float根据其定义 - 根据double传递的方式,它可能会读取高阶 32 位或低阶 32。

在这种情况下,它确实读取了低 32 位,从而产生了float具有位模式的值

0x60000000

它有一个有偏指数0xC0 = 192, 对应于无偏指数192 - 127 = 65和 有效数1.000000. 换句话说,这float就是

2^65 = 36893488147419103232

这是打印的值。

于 2013-05-18T23:10:13.503 回答