narrowing conversion from unsigned to double

2019-01-11 17:01发布

问题:

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

g++ 4.7.1 complains about this code:

warning: narrowing conversion of 'u' from 'unsigned int' to 'double' inside { }

Why is this a narrowing conversion? Isn't every unsigned perfectly representable as a double?

回答1:

Why is this a narrowing conversion?

Because the definition includes (with my emphasis):

C++11 8.5.4/7 A narrowing conversion is an implicit conversion [...] from an integer type [...] to a floating-point type, except where the source is a constant expression and the actual value after conversion will fit into the target type and will produce the original value when converted back to the original type.

u is not a constant expression, so it's a narrowing conversion whether or not all possible values of the source type might be representable in the target type.

Isn't every unsigned perfectly representable as a double?

That's implementation defined. In the common case of 32-bit unsigned and double with a 52-bit mantissa, that is the case; but some implementations have larger unsigned and/or smaller double representations, so code that depends on that assumption is not portable.



回答2:

The warning you have because you initialize x with non-constant expression

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$ 

As you can see the code above works without any warning or errors



回答3:

(Let's try:) double has exactly 52 bits of significant (binary) digits (according to ieee standard), whereas unsigned int may have good 64 bits on some other system. So the actual unsigned int's width on your system may be of no value for this check.