Сужение конверсии от неподписанного до двойного
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
?
3 ответа
Почему это сужение конверсии?
Потому что определение включает (с моим акцентом):
C++ 11 8.5.4 / 7 Сужающее преобразование - это неявное преобразование [...] из целочисленного типа [...] в тип с плавающей запятой, за исключением случаев, когда источником является константное выражение и фактическое значение после преобразование будет соответствовать целевому типу и даст исходное значение при преобразовании обратно в исходный тип.
u
не является константным выражением, поэтому это сужающее преобразование, независимо от того, могут ли все возможные значения исходного типа быть представляемыми в целевом типе.
Не каждый
unsigned
прекрасно представлен какdouble
?
Это реализация определена. В общем случае 32-битный unsigned
а также double
с 52-битной мантиссой, это так; но некоторые реализации имеют больший unsigned
и / или меньше double
представления, поэтому код, который зависит от этого предположения, не является переносимым.
Предупреждение, которое вы получили, потому что вы инициализируете 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$
Как вы можете видеть код выше работает без каких-либо предупреждений или ошибок
(Давай попробуем:) double
имеет ровно 52 бита значащих (двоичных) цифр (согласно стандарту ieee), тогда как unsigned int
может иметь хорошие 64 бит в другой системе. Так актуально unsigned int
Ширина вашей системы может не иметь значения для этой проверки.