Подтвердить что ты не робот

Продвижение по плавающей запятой: стростюп против компилятора - кто прав?

В разделе 10.5.1 новой статьи Stroustrup "Язык программирования С++ - четвертое издание" он говорит, что перед выполнением арифметической операции интегральное продвижение используется для создания ints из более коротких целочисленных типов, и аналогичным образом, точечное продвижение используется для создания двойников из поплавков.

Я подтвердил первое требование со следующим кодом:

#include <iostream>
#include <typeinfo>

int main()
{
    short a;
    short b;
    std::cout << typeid(a + b).name() << std::endl;
}

Это выводит "int" с vС++ и "i" с gcc.

Но тестируя его с помощью float вместо коротких замыканий, выход по-прежнему остается "float" или "f":

#include <iostream>
#include <typeinfo>

int main()
{
    float a;
    float b;
    std::cout << typeid(a + b).name() << std::endl;
}

В соответствии с Stroustrup нет исключений из правила продвижения с плавающей запятой, поэтому я ожидал вывод "double" или "d".

Является ли упомянутый раздел о рекламных акциях неправильным или каким-то образом неясным? И есть ли разница в С++ 98 и С++ 11 относительно продвижения по типу?

4b9b3361

Ответ 1

Я не знаю, что говорит книга Страуступа, но в соответствии со стандартом float в этом случае не будет преобразован в double. Перед применением большинства арифметических двоичных операторов применяются обычные арифметические преобразования, описанные в 5p9:

  • Если либо операнд имеет тип перечисления с областью (7.2), конверсии не выполняются; если другой операнд не имеет одного и того же типа, выражение плохо сформировано.
  • Если один из операндов имеет тип long double, другой должен быть преобразован в длинный double.
  • В противном случае, если один из операндов является двойным, другой должен быть преобразован в double.
  • В противном случае, если любой операнд является float, другой должен быть преобразован в float.
  • В противном случае интегральные акции (4.5) должны выполняться на обоих операндах. [...]

Интегральные акции - это то, что приводит к преобразованию двух short в int s. Но два float не будут преобразованы в double в соответствии с этими правилами. Если вы добавите float в double, float будет преобразован в double.

Вышеизложенное из С++ 11. С++ 03 содержит те же правила, за исключением тех, которые относятся к облачным перечислениям.

Ответ 2

Тем временем Страуструп, похоже, признал, что предложение о назначении неверно или, по крайней мере, вводит в заблуждение. Он удалил предложение о продвижении с плавающей запятой из раздела 10.5.1.

Пожалуйста, просмотрите errata третьего издания 4-го издания на веб-странице Stroustrup:

pg 267: s/Аналогично, продвижение с плавающей запятой используется для создания двойников из поплавков //

(Примечание: выражение s/regexp/replacement/похоже на семантику sed unix. Он ищет шаблон regexp и заменяет его заменой. Ничего в нашем случае.)