Сужение преобразования от беззнакового до двойного
static_assert(sizeof(unsigned) == 4, ":(");
static_assert(sizeof(double) == 8 ,":(");
unsigned u{42};
double x{u};
g++ 4.7.1 жалуется на этот код:
warning: narrowing conversion of 'u' from 'unsigned int' to 'double' inside { }
Почему это сужение? Разве не все unsigned
прекрасно представлены как double
?
Ответы
Ответ 1
Почему это сужение?
Поскольку определение включает (с моим упором):
С++ 11 8.5.4/7 Сужение преобразования - это неявное преобразование [...] из целочисленного типа [...] в тип с плавающей запятой, , за исключением случаев, когда источник является постоянным выражением, а фактическое значение после преобразования будет соответствовать целевому типу и будет выведите исходное значение при преобразовании обратно в исходный тип.
u
не является постоянным выражением, поэтому оно сужает преобразование того, могут ли быть представлены все возможные значения типа источника в целевом типе.
Разве не все unsigned
прекрасно представлены как double
?
Эта реализация определена. В общем случае 32-разрядных unsigned
и double
с 52-битной мантиссой это так; но некоторые реализации имеют более крупные unsigned
и/или меньшие double
представления, поэтому код, который зависит от этого предположения, не переносится.
Ответ 2
Предупреждение, которое у вас есть, потому что вы инициализируете x с непостоянным выражением
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$
Как вы можете видеть, код выше работает без каких-либо предупреждений или ошибок
Ответ 3
(Попробуйте:) double
имеет ровно 52 бита значащих (двоичных) цифр (в соответствии с стандартом ieee), тогда как unsigned int
может иметь хорошие 64 бита в некоторой другой системе. Таким образом, фактическая ширина unsigned int
в вашей системе может не иметь значения для этой проверки.