9

从另一个问题中,他们谈到了 Bjarne Stroustrup 是如何说的,就像比 an 更窄的整数数据类型int(例如short)被提升为 an一样intfloats 也被提升为 a double。但是,与比 更窄的积分的扩展不同int浮点提升不会以相同的方式发生,而是发生在其他地方。

我知道,如果您要计算float + double,则在应用二元运算符()之前float将转换为 a 。但是,根据Learncpp.com,这不是浮点推广。这是通常的算术转换double+

浮点提升何时真正发生?

4

2 回答 2

16

每个 [conv.fpprom] 都有“浮点提升”之类的东西floatdouble

类型的纯右值float可以转换为类型的纯右值double。值不变。

这种转换称为浮点提升。

链接问题的答案是正确的。float由于通常的算术转换不会提升浮点操作数,因此在添加两个 s 时不应自动发生此提升。

当将 a作为操作数传递给省略号时,确实会发生浮点提升,例如 in 。这就是格式说明符打印 a或 a的原因:如果您传递 a ,该函数实际上接收 a ,这是提升的结果。floatprintf%ffloatdoublefloatdouble

浮点提升的存在在重载解析中也很重要,因为整数提升和浮点提升比整数转换、浮点转换和浮点整数转换具有更好的隐式转换等级。

示例 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);

这是模棱两可的。从floatto的转换long double并不比从floatto的转换好,int因为它们都不是促销活动。

示例 3:

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

这调用operator float然后将结果float值提升double为初始化d

于 2015-05-27T18:57:37.953 回答
6

应用浮点提升的主要(可能是唯一的)时间是在将参数传递给可变参数函数(例如,printf)时。

在这种情况下,通常的算术转换不适用(它们用于在表达式中的两个操作数之间查找公共类型)。

标准的相关部分是 [expr.call]/7(至少从 N4296 开始):

当给定参数没有参数时,参数的传递方式使得接收函数可以通过调用 va_arg (18.10) 获取参数的值。
[...]
如果参数具有受整数提升 (4.5) 约束的整数或枚举类型,或受浮点提升 (4.6) 约束的浮点类型,则参数的值将转换为在调用之前提升类型。

于 2015-05-27T18:47:39.357 回答