Бьерн Страуструп. Язык программирования С++. Специальное издание (2011) (1004033), страница 207
Текст из файла (страница 207)
Литералы с плавающей точкой (54.5.1) можно использовать, преобразовав их явным образом в интегральный тип. Функции, классовые обьекты, указатели и ссылки можно использовать в качестве операндов операции в!хеа!'66.2). С интуитивной точки зрения, константные выражения — это просто выражения, которые компилятор может вычислить до начала компоновки программы (89.1) и ее запуска на выполнение.
С.6. Неявное преобразование типов Интегральные типы и типы с плавающей запятой (84.!.1) можно свободно смешивать в арифметических выражениях и операциях присваивания. По возможности значения преобразуются таким образом, чтобы не терять информацию. К сожалению, преобразования с потерей значений также могут выполняться неявно. В на- Приложение С Технические подробности 988 стоящем разделе приведены правила преобразований, связанные с этим проблемы и их решения. С.6.1. Продвижения (ргопзо11опв) Неявные преобразования, сохраняющие значения, называют продвижениями (ргото11опз). Перед выполнением арифметической операции выполняется интегральное продвижение (!пгеяга1 ргото!1оп) с целью получения значений типа 1пг из более коротких целых типов.
Заметьте, что эти продвижения не продолжаются в сторону !опя (если только не задействован тип )«айаг г или элемент перечисления со значением, слишком большим для 1пг). Это соответствует исходной цели таких продвижений в языке С: привести операнды к естественным размерам для арифметических операций. Интегральные продвижения таковы: ° сйаг, з!ипе«! сйаг, ипз(япе«! айаг, зйогг !и! или ипз!Вие«! зйогг !и!преобразуются в гпг, если гп! может отобразить все значения исходного типа; в противном случае они преобразуются в ипз!Впе«! шг. ° исйаг г (94.3) или перечисления (94.8) преобразуются к первому из перечисленных ниже типов, способному отобразить все их значения: !пб ипз(яие«! 1пг, !опй или иггз!!!лед !опя.
° Битовые поля (5С.В.!) преобразуются в !пг, если изг может представить все значения битового поля; в противном случае осуществляется преобразование в ипз1япе«! гпг, если этот тип может представить все значения битового поля. В противном случае никакого интегрального продвижения не выполняется вообще. ° Тип Ьоо! преобразуется в!пг, !а!зе становится нулем, а ггие — единицей.
Продвижения используются как часть обычных арифметических преобразований (5С.Ь.З). С.6.2. Преобразования Фундаментальные типы могут преобразовываться друг в друга огромным количеством способов. По моему мнению, позволено слишком много преобразований. Например; го1д Т(доиЫе д) сваг с = д«У внимание: доиЫв преобразуется и сНаг ) При написании программ вы должны стремиться избегать неопределенного поведения и преобразований, которые незаметным образом «выбрасывают» информацию. Компилятор может предупредить о многих сомнительных преобразованиях.
По счастью, многие компиляторы так и делают. С.8.2.1. Интегральные преобразования Целое может преобразовываться в иной целый тип. Значение перечислимого типа может преобразовываться к целому типу. С.б. Неявное преобразование типов 969 Если целевой тип беззнаковый, результирующее значение есть просто такой набор битов исходного значения, который помещается в целевом типе (старшие биты при необходимости отбрасываются).
Точнее, результат будет наименьшим беззнаковым целым, соответствующим остатку от деления исходного целого на 2 в степени и, где и — это число битов, применяемых для представления беззнакового целого. Например: ипв(хпег! сваг ис = 1023; ~У 11111!!!11; ис становитсл 1!1111! 1, то есть 255 Когда целевой тип знаковый, значение остается неизменным, если оно представимо целевым типом; в противном случае результат зависит от реализации: в10пеИ свае зс = 1023; 11 зависит от реализации Возможны следующие результаты; 127 и -1 (5С.3.4). Логическое значение или значение перечислимого типа могут неявно преобразовываться в свой целочисленный эквивалент Ц4.2, 84.8).
С.6.2.2. Преобразования чисел с плавающей запятой Значение с плавающей запятой может быть преобразовано в иной тип с плавающей запятой. Если исходное значение точно представимо в целевом типе, результат совпадает с исходным числовым значением. Если исходное значение располагается между двумя соседними значениями целевого типа, результат будет одним из этих значений. В противном случае результат не определен. Например: фоат Т= Н.Т МАХ; Иоиб!е И=Г; Яоаг12 = Вг г(оиВ1е в!3 = РВ1, МАХ! !)оаг 13 = Взз У наибольшее значение типа Воаг ~У о/си!= =1' В оВ.72 ==Т В наибольшее значение типа ВоиЫе В не определено, если РВТ МАХ<РВ1, МАХ !по* р = ! ! ! 1 ! ! 1 ! НЛН 111!1 Н111. ! 1 1 ! ! Тип Т' может неявно преобразовываться в сонат Т* (85.4.1). Аналогично, Ть может неявно преобразовываться в сопи Ть.
С.6.2.3. Преобразования указателей и ссылок Указатель на любой тип объекта может неявно преобразовываться в тип еоЫ* (85.6). Указатель (ссылка) на производный класс может неявно преобразовываться в тип указателя (ссылки) на доступный и недвусмысленно определяемый базовый класс (912.2). Отметим, что указатель на функцию или указатель на член класса не могут неявно преобразовываться в тип воЫ*. Константное выражение (8С.5), значением которого служит О, может неявно преобразовываться в любой указательный тип или тип указателя на член класса (95.1.1). Например; Приложение С. Технические подробности 970 С.6.2.4.
Преобразования указателей на члены классов Указатели и ссылки на члены классов могут неявно преобразовываться так, как описано в з15.5.1. го147(1пг* р, 1п(1) Ьоог и пот сего = р; Ьоо1 Ь2 =1; //(гне если р(=0 // о не если П=О С.6.2.6. Преобразованияазначениеинтегральноготипа — значение с плавающей запятой» Когда значение с плавающей запятой преобразуется в целое значение, его дробная часть отбрасывается. Другими словами, преобразование из числа с плавающей запятой в целое урезает исходное значение.
Например, значение тг(1.6) равно 1. Если урезанное значение не может быть представлено целевым типом, то результат не определен. Например: 1пг 1 = 2. 7; слог Ь = 2000. 7; // становится 2 // не определено для 8-битных сваг Преобразование из целых в типы с плавающей запятой с математической точки зрения корректно настолько, насколько это позволяет аппаратура. По~еря точности происходит в тех случаях, когда целое значение не удается точно представить в виде значения с плавающей запятой.
Например, следующее выражение тг 1 = 1)оа< (1234567890); оставит 1 со значением 1234567936 на машине с 32-битовыми гпг и 11оаг. Ясно, что лучше избегать преобразований, которые потенциально могут исказить исходное значение. Компиляторы могут выявить и предупредить об очевидно наиболее опасных преобразованиях, таких как преобразование числа с плавающей запятой в целое, или 1оп8 1пг в сйаг. Однако в общем случае, выявление всех особенностей преобразований на этапе компиляции недостижимо, так что программисты не должны терять бдительности. Когда одной лишь бдительности недостаточно, можно вставить явные проверки.
Например: сгавв слесз 5аИеИ ( ); слог сдесзед (1п( 1) ( слог с = 1( //тагнтан по( роггаЫе фС.6.2.!) ту(1 ! = с) сдгот слесз /а/1ей(); ге(иго с; ) гоИ ту соФе(1пг 1) С.6.2.6. Преобразования в логический тип Указатели, значения интегральных типов и типов с плавающей запятой могут неявно преобразовываться в тип Ьоо1(З4.2).
Ненулевые значения преобразовываются в ггие, а нулевые — в 1айе. Например: 971 С7. Многомерные массивы сйаг с = сйесйеН (!) гу ) Гарантированно контролируемые и переносимые урезания при преобразованиях требуют применения пипгег)с !1«иге (922.2). С.6.3. Обычные арифметические преобразования Эти преобразования выполняются над операндами любой бинарной (двухоперандной) операции, чтобы привести их к одному обшему типу, который затем используется для типа результата операции: 1. Если один из операндов относится к типу 1«ля Ио«Ые, то другой операнд преобразуется к типу 1ощ г(о«Ые. ° В противном случае, если один из операндов относится к типу Но«Ые, то другой операнд преобразуется в Но«Ые. ° В противном случае, если один из операндов имеет тип Яоаг, то другой преобразуется к типу 77«аа ° В противном случае над обоими операндами выполняются интегральные продвижения (~С.б.)).
2. Затем, если один из операндов относится к типу ипз!пиес( 1олд, то другой операнд преобразуется к и«залег! 1ощ. ° В противном случае, если один из операндов относится к типу 1«ля Ыб а другой — к типу ииз!пиес! 1«б то если!ощ Ыг в состоянии представить все значения типа ипз!яисч! ид операнд типа и«я!илес! т! преобразуется в 1«пи !лг, иначе оба операнда преобразуются к типу «пяяпеИ!ощ 1«п ° В противном случае, если один из операндов относится к типу 1ощ, то другой операнд преобразуется в !оп». ° В противном случае, если один из операндов относится к типу ипз)ялеН, то другой операнд преобразуется в иле!япеИ. ° В противном случае оба операнда 1«с С.7.