不,真的,浮点提升什么时候发生?
No really, when does floating point promotion actually happen?
从另一个 QUESTION 他们谈论 Bjarne Stroustrup 是如何说的,就像比 int
(例如 short
)窄的整数数据类型被提升为 int
,float
被提升为 double
。然而,与扩大比 int
更窄的积分不同, 浮点提升 不会以相同的方式发生,而是发生别处。
我知道,如果您要计算 float + double
,则 float
会在应用二元运算符 (+
) 之前转换为 double
。然而,根据Learncpp.com,这不是浮点提升。这是普通算术转换.
浮点提升实际发生在什么时候?
应用浮点提升的主要(可能唯一)时间是将参数传递给可变参数函数(例如,printf
)。
在这种情况下,通常的算术转换不适用(它们用于查找表达式中两个操作数之间的公共类型)。
标准的相关部分是 [expr.call]/7(至少从 N4296 开始):
When there is no parameter for a given argument, the argument is passed in such a way that the receiving function can obtain the value of the argument by invoking va_arg (18.10).
[...]
If the argument has integral or enumeration type that is subject to the integral promotions (4.5), or a floating point type that is subject to the floating point promotion (4.6), the value of the argument is converted to the promoted type before the call.
每个 [conv.fpprom].
中有 float
到 double
这样的事情
A prvalue of type float
can be converted to a prvalue of type double
. The value is unchanged.
This conversion is called floating point promotion.
链接问题的答案是正确的。添加两个 float
时不应自动进行此提升,因为通常的算术转换不会提升浮点操作数。
当将 float
作为操作数传递给省略号时, 会发生浮点数提升,例如 printf
。这就是 %f
格式说明符打印 float
或 double
的原因:如果您传递 float
,函数实际上接收 double
,结果促销。
浮点数提升的存在在重载决策中也很重要,因为整数promotions和浮点数promotions有更好的隐式转换排名高于积分 conversions、浮点 conversions 和浮点积分 conversions.
示例 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
。
从另一个 QUESTION 他们谈论 Bjarne Stroustrup 是如何说的,就像比 int
(例如 short
)窄的整数数据类型被提升为 int
,float
被提升为 double
。然而,与扩大比 int
更窄的积分不同, 浮点提升 不会以相同的方式发生,而是发生别处。
我知道,如果您要计算 float + double
,则 float
会在应用二元运算符 (+
) 之前转换为 double
。然而,根据Learncpp.com,这不是浮点提升。这是普通算术转换.
浮点提升实际发生在什么时候?
应用浮点提升的主要(可能唯一)时间是将参数传递给可变参数函数(例如,printf
)。
在这种情况下,通常的算术转换不适用(它们用于查找表达式中两个操作数之间的公共类型)。
标准的相关部分是 [expr.call]/7(至少从 N4296 开始):
When there is no parameter for a given argument, the argument is passed in such a way that the receiving function can obtain the value of the argument by invoking va_arg (18.10).
[...]
If the argument has integral or enumeration type that is subject to the integral promotions (4.5), or a floating point type that is subject to the floating point promotion (4.6), the value of the argument is converted to the promoted type before the call.
每个 [conv.fpprom].
中有float
到 double
这样的事情
A prvalue of type
float
can be converted to a prvalue of typedouble
. The value is unchanged.This conversion is called floating point promotion.
链接问题的答案是正确的。添加两个 float
时不应自动进行此提升,因为通常的算术转换不会提升浮点操作数。
当将 float
作为操作数传递给省略号时, 会发生浮点数提升,例如 printf
。这就是 %f
格式说明符打印 float
或 double
的原因:如果您传递 float
,函数实际上接收 double
,结果促销。
浮点数提升的存在在重载决策中也很重要,因为整数promotions和浮点数promotions有更好的隐式转换排名高于积分 conversions、浮点 conversions 和浮点积分 conversions.
示例 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
。