Нет, действительно, когда действительно происходит продвижение с плавающей запятой?

Из этого другого ВОПРОС они говорят о том, как Бьярн Страуструп сказал, что точно так же, как целочисленные типы данных, более узкие, чем int (например, short), повышаются до int, floats повышаются до double. Однако, в отличие от расширения интегралов, более узких, чем int, расширение числа с плавающей запятой не происходит таким же образом, а вместо этого происходит в другом месте.

Я знаю, что если бы вы вычислили float + double, float было бы преобразовано в double до применения бинарного оператора (+). Однако это не реклама с плавающей запятой в соответствии с Learncpp.com. Это обычное арифметическое преобразование.

Когда на самом деле происходит продвижение с плавающей запятой?


person Wandering Fool    schedule 27.05.2015    source источник
comment
прочитайте комментарии и ответы, вы увидите, что книга Бьярна ошибочна.   -  person Richard Hodges    schedule 27.05.2015
comment
возможный дубликат продвижения с плавающей запятой: stroustrup против компилятора - кто правильно?   -  person Richard Hodges    schedule 27.05.2015
comment
@RichardHodges Я прочитал комментарии. Даже если этот небольшой отрывок был удален из книги, это не говорит мне о том, что продвижение с плавающей запятой было удалено из языка. Я до сих пор не знаю, когда может произойти продвижение с плавающей запятой.   -  person Wandering Fool    schedule 27.05.2015


Ответы (2)


Существует такая вещь, как «продвижение с плавающей запятой» от float до double на [conv.fpprom].

Значение prvalue типа float можно преобразовать в значение prvalue типа double. Значение не изменилось.

Это преобразование называется продвижением с плавающей запятой.

Ответы на связанный вопрос верны. Это преобразование не должно происходить автоматически при добавлении двух float, поскольку обычные арифметические преобразования не продвигают операнды с плавающей запятой.

Повышение числа с плавающей запятой действительно происходит при передаче float в качестве операнда многоточию, как в printf. Вот почему спецификатор формата %f печатает либо float, либо double: если вы передаете float, функция фактически получает double, результат повышения.

Существование продвижения с плавающей запятой также важно для устранения перегрузки, потому что интегральные повышения и повышения с плавающей запятой имеют более высокий ранг неявной конверсии, чем интегральные конверсии. , преобразования с плавающей запятой и преобразования с плавающей запятой.

Пример 1:

void f(double);
void f(long double);
f(0.0f);

Это вызывает void f(double), так как повышение до double лучше, чем преобразование в long double. Напротив, рассмотрим этот, возможно, удивительный пример 2:

void f(long double);
void f(int);
f(0.0f);

Это неоднозначно. Преобразование из float в long double не лучше, чем преобразование из float в int, поскольку оба они не являются рекламными акциями.

Пример 3:

struct S {
    operator float();
    operator int();
};
double d = S();

Это вызывает operator float, а затем повышает полученное значение float до double для инициализации d.

person Brian Bi    schedule 27.05.2015
comment
Ваш ответ такой подробный и содержит отличные примеры. Теперь я полностью получаю продвижение с плавающей запятой. Большое спасибо! - person Wandering Fool; 27.05.2015
comment
Разве float to long double не является продвижением по службе, а не конверсией? - person ZeZNiQ; 29.01.2020

Основное (возможно, единственное) время, когда применяются продвижения с плавающей запятой, — это передача аргумента функции с переменным числом переменных (например, printf).

В этом случае обычные арифметические преобразования не применяются (они предназначены для нахождения общего типа между двумя операндами в выражении).

Соответствующая часть стандарта — [expr.call]/7 (по крайней мере, начиная с N4296):

Когда для данного аргумента нет параметра, аргумент передается таким образом, что принимающая функция может получить значение аргумента, вызвав va_arg (18.10).
[...]
Если аргумент имеет целочисленный тип или тип перечисления, который подлежит целочисленному расширению (4.5), или тип с плавающей запятой, который подлежит расширению с плавающей запятой (4.6), значение аргумент преобразуется в продвигаемый тип перед вызовом.

person Jerry Coffin    schedule 27.05.2015
comment
Вы говорите о преобразовании типов? Я знаю, что преобразование типа происходит, если вы передаете число с плавающей запятой функции с переменным числом аргументов, которая имеет двойной параметр. Я не верю, что преобразование типов и продвижение с плавающей запятой — это одно и то же. Если вы имели в виду что-то другое, не могли бы вы уточнить? - person Wandering Fool; 27.05.2015
comment
Ой! Вы говорите об эллипсах. Где параметр может быть любым значением и любым количеством значений. Вот где может произойти продвижение с плавающей запятой. Спасибо! - person Wandering Fool; 27.05.2015