鉴于以下内容......
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
我对最后一个错过了什么?
答案 0 :(得分:12)
您需要在使用前声明fark
。如第6.5.2.2节第6段所述:
如果表示被调用函数的表达式具有不包含原型的类型,则对每个参数执行整数提升,并将类型为
float
的参数提升为{{1} } 即可。这些被称为默认参数促销。
(我大胆强调)。
请注意,使用与隐式假定类型不兼容的类型定义double
是违反约束的,并且如果调用和定义位于同一转换单元中,则需要编译器发出诊断消息。 gcc只会警告,但是clang会拒绝代码[fark
]。如果调用和定义在不同的翻译单元中,编译器当然不能诊断错误,但是通过具有不兼容类型的表达式调用函数在任何情况下都会调用未定义的行为。
当值error: conflicting types for 'fark'
转换为0.7f
时(我假设double
使用IEEE754 32位表示,float
使用IEEE754 64位表示法,你得到一个值
double
其位模式(十六进制表示法)为
0.699999988079071
(偏差指数为1022,对应有效指数0x3FE6666660000000
,有效数为-1
)。
将其传递到堆栈或寄存器 - 1.6666660000000
。
当fark
从该表示中读取32位时 - 因为它期望每个定义fark
- 取决于float
的传递方式,它可能会读取更高阶32位或低位32。
在这种情况下确实读取了低位32位,导致带有位模式的double
值
float
的偏差指数为0x60000000
,对应于无偏指数0xC0 = 192
和有效数192 - 127 = 65
。换句话说,那是
1.000000
表示
float
这是打印的值。