Из этого другого ВОПРОС они говорят о том, как Бьярн Страуструп сказал, что такие же интегральные типы данных, что и int
(например. short
) повышены до int
, float
s повышены до double
, Однако в отличие от расширения интегралов уже int
, продвижение с плавающей запятой не происходит таким же образом, но вместо этого происходит в другом месте.
Я знаю, что если бы вы рассчитали float + double
float
будет преобразован в double
перед бинарным оператором (+
) применены. Однако это не продвижение с плавающей запятой в соответствии с Learncpp.com. Это обычное арифметическое преобразование.
Когда происходит продвижение с плавающей запятой?
Существует такая вещь, как «продвижение с плавающей запятой» float
в double
за [conv.fpprom].
Prvalue типа
float
может быть преобразовано в тип значения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
,
Основное (возможно, единственное) время, когда применяются преобразования с плавающей запятой, — это передача аргумента в функцию с переменным числом (например, printf
).
В этом случае обычные арифметические преобразования не применяются (они предназначены для поиска общего типа между двумя операндами в выражении).
Соответствующей частью стандарта является [expr.call] / 7 (по крайней мере, начиная с N4296):
Когда для данного аргумента нет параметра, аргумент передается таким образом, что принимающая функция может получить значение аргумента, вызвав va_arg (18.10).
[…] Если аргумент имеет целочисленный тип или тип перечисления, который является объектом повышенного преобразования (4.5), или тип с плавающей запятой, который является объектом повышенного преобразования с плавающей запятой (4.6), значение аргумента преобразуется в повышенный тип перед вызовом ,