-1

对于以下表达式:-

int main()
{
    unsigned ui = 1;
    float fval = 2.5;
    cout << sizeof(ui) << endl << sizeof(fval) << endl;
    cout << typeid(ui+fval).name();
}

我们得到以下输出:-

4
4
f

似乎 ui+fval 是一个浮点数。

但是,鉴于 float 和 unsigned int 都是 4 个字节,并且并非所有 unsigned int 值都可以放入 float,所以 fval 不应该转换为 unsigned int 吗?

4

1 回答 1

2

算术运算符的规则实际上与一般函数重载决议的规则略有不同。

来自算术运算符的 cppreference :

转换

如果传递给算术运算符的操作数是整数或无作用域枚举类型,则在任何其他操作之前(但在左值到右值转换之后,如果适用),操作数会经历整数提升。如果操作数具有数组或函数类型,则应用数组到指针和函数到指针的转换。

对于二元运算符(移位除外),如果提升的操作数具有不同的类型,则应用附加的隐式转换集,称为通常的算术转换,其目标是生成通用类型(也可通过std::common_type类型特征访问)。如果在任何整数提升之前,一个操作数是枚举类型,而另一个操作数是浮点类型或不同的枚举类型,则不推荐使用此行为。(C++20 起)

  • 如果任一操作数具有范围枚举类型,则不执行转换:另一个操作数和返回类型必须具有相同的类型
  • 否则,如果任一操作数为long double,则将另一个操作数转换为long double
  • 否则,如果任一操作数为double,则将另一个操作数转换为double
  • 否则,如果任一操作数为float,则将另一个操作数转换为float

[剪辑]

因此,非常明确地,当我们执行 时unsigned + floatunsigned将转换为float. 这是适用的第一条规则,所以我们遵循它。

但是,对于一般的重载决议,从unsignedtofloat的转换等同于从 to 的float转换unsigned。因此,例如在以下代码片段中:

unsigned add(unsigned l, unsigned r) { return l + r;  }
float add(float l, float r) { return l + r;  }

int main()
{
    unsigned ui = 1;
    float fval = 2.5;
    add(ui, fval);
}

它无法决定add使用哪个版本并且无法编译。

于 2021-07-28T15:05:27.210 回答