C中的隐式类型转换

vog*_*err 7 c floating-point type-conversion

我偶然发现了维基百科上的以下示例(http://en.wikipedia.org/wiki/Type_conversion#Implicit_type_conversion).

#include <stdio.h>

int main()
{
    int i_value   = 16777217;
    float f_value = 16777217.0;
    printf("The integer is: %i\n", i_value); // 16777217
    printf("The float is:   %f\n", f_value); // 16777216.000000
    printf("Their equality: %i\n", i_value == f_value); // result is 0
}
Run Code Online (Sandbox Code Playgroud)

他们的解释是:"这种奇怪的行为是由于i_value与f_value进行比较时隐式转换为浮动;一个失去精度的转换,使得比较的值不同."

这不对吗?如果i_value被转换为浮动,那么两者都会有相同的精度损失并且它们是相等的.所以i_value必须加倍.

caf*_*caf 7

不,在等于运算符的情况下,会发生"通常的算术转换",它开始于:

  • 首先,如果任一操作数的相应实数类型是long double,则另一个操作数在不改变类型域的情况下被转换为其对应的实数类型的类型long double.
  • 否则,如果任一操作数的相应实数类型是double,则另一个操作数在不改变类型域的情况下被转换为其对应的实数类型的类型double.
  • 否则,如果任一操作数的相应实数类型是float,则另一个操作数在不改变类型域的情况下被转换为其对应的实数类型的类型float.

最后一种情况适用于:i_value转换为float.

尽管如此,你可以从比较中看到一个奇怪的结果的原因是因为对通常的算术转换的这个警告:

浮动操作数的值和浮动表达式的结果可以以比该类型所需的精度和范围更高的精度和范围来表示; 因此不改变类型.

这就是正在发生的事情:转换的类型i_value仍然是float,但在此表达式中,您的编译器正在利用此纬度并以更高的精度表示它float.这是编译387兼容浮点时的典型编译器行为,因为编译器在浮点堆栈上保留临时值,浮点堆栈以80位扩展精度格式存储浮点数.

如果您的编译器是gcc,您可以通过提供-ffloat-store命令行选项来禁用此额外的精度.