C中的隐式类型转换

我在维基百科( 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
}

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

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

解决方法

不,在等于运算符的情况下,会发生“通常的算术转换”,它开始于:
  • First,if the corresponding real type of either operand is long double,the other operand is converted,without change of type
    domain,to a type whose corresponding real type is long double.
  • Otherwise,if the corresponding real type of either operand is double,to a type whose corresponding real type is double.
  • Otherwise,if the corresponding real type of either operand is float,to a type whose corresponding real type is float.

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

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

The values of floating operands and of the results of floating
expressions may be represented in greater precision and range than
that required by the type; the types are not changed thereby.

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

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

相关文章

/** C+⬑ * 默认成员函数 原来C++类中,有6个默认成员函数: 构造函数 析构函数 拷贝...
#pragma once // 1. 设计一个不能被拷贝的类/* 解析:拷贝只会放生在两个场景中:拷贝构造函数以及赋值运...
C类型转换 C语言:显式和隐式类型转换 隐式类型转化:编译器在编译阶段自动进行,能转就转,不能转就编译...
//异常的概念/*抛出异常后必须要捕获,否则终止程序(到最外层后会交给main管理,main的行为就是终止) try...
#pragma once /*Smart pointer 智能指针;灵巧指针 智能指针三大件//1.RAII//2.像指针一样使用//3.拷贝问...
目录&lt;future&gt;future模板类成员函数:promise类promise的使用例程:packaged_task模板类例程...