C++ 缩小从无符号到双精度的转换范围

C++ 缩小从无符号到双精度的转换范围,c++,c++11,warnings,double,type-conversion,C++,C++11,Warnings,Double,Type Conversion,g++4.7.1抱怨此代码: static_assert(sizeof(unsigned) == 4, ":("); static_assert(sizeof(double) == 8 ,":("); unsigned u{42}; double x{u}; 为什么这是一个缩小的转换?不是每个无符号的都可以完美地表示为双精度的 由于使用非常量表达式初始化x而产生的警告 warning: narrowing conversion of 'u' from 'unsigned int' to 'do

g++4.7.1抱怨此代码:

static_assert(sizeof(unsigned) == 4, ":(");
static_assert(sizeof(double) == 8 ,":(");
unsigned u{42};
double x{u};

为什么这是一个缩小的转换?不是每个
无符号的
都可以完美地表示为
双精度的

由于使用非常量表达式初始化x而产生的警告

warning: narrowing conversion of 'u' from 'unsigned int' to 'double' inside { }
正如您所看到的,上面的代码工作时没有任何警告或错误(让我们试试:)
double
有52位有效(二进制)数字(根据ieee标准),而
unsigned int
在其他系统上可能有好的64位。因此,系统上的实际
无符号int
宽度可能对此检查没有价值

为什么这是一个缩小的转换

因为定义包括(我强调):

C++11 8.5.4/7缩小转换是一种隐式转换 […]从整数类型[…]到浮点类型,除非源是常量表达式,否则转换后的实际值将适合目标类型,并在转换回原始类型时生成原始值

u
不是一个常量表达式,因此,无论源类型的所有可能值是否都可以在目标类型中表示,这都是一个缩小范围的转换

不是每个
无符号的
都可以完美地表示为
双精度的


这是实现定义的。在32位
无符号
和带有52位尾数的
双精度
的常见情况下,就是这种情况;但有些实现具有较大的
无符号
和/或较小的
双精度
表示,因此依赖于该假设的代码是不可移植的。

双精度类型的最大值为:1.79769e+308,无符号int为0xFFFFFF。。所以不,它不能完美地表示为双重身份。这看起来可能有关联:。@paulm:嗯?一个<代码>双有一个53位尾数,因此它可以代表所有32位无符号的int。@ OLICHARLISVES: IEEE BIANY64代码<双<代码>可能是这样的,但是C++不需要IEEE算术,或者64位<代码>双< /代码>,或者32位<代码>未签名< /C> >。@ MikeSeymour:当然。但是编译器需要警告一般情况吗?
s/52/53/
:IEEE 754 binary64有53位有效位,52位存储,1位隐式。最可笑的是,即使是
char x='3';双y{x}也是一个缩小转换错误。从
char
double
的转换是一种变窄转换!53位有效数字。52被存储,1是隐式的。
Ilyas-iMac:TestC++11 sandye51$ cat main.cpp                   
int main()
{
    static_assert(sizeof(unsigned) == 4, ":(");
    static_assert(sizeof(double) == 8 ,":(");
    constexpr unsigned u{42};
    double x{u};

    return 0;
}Ilyas-iMac:TestC++11 sandye51$ gcc -o main main.cpp -std=c++11
Ilyas-iMac:TestC++11 sandye51$