命名空间
变体
操作

常用算术转换

来自 cppreference.com
< cpp‎ | 语言
 
 
C++ 语言
 
 

许多需要 算术枚举 类型的操作数的二元运算符会导致转换并以类似的方式生成结果类型。其目的是生成一个公共类型,这也是结果的类型。这种模式称为常用算术转换

内容

[编辑] 定义

常用算术转换定义如下

[编辑] 阶段 1

左值转换为右值转换 应用于两个操作数,生成的右值在剩余流程中用于代替原始操作数。

[编辑] 阶段 2

  • 如果任一操作数是 作用域枚举类型,则不执行任何转换;如果另一个操作数没有相同的类型,则表达式是非法的。
  • 否则,继续下一个阶段。
(自 C++11 起)

[编辑] 阶段 3

  • 如果任一操作数是 枚举类型,而另一个操作数是不同的枚举类型或浮点类型,则表达式是非法的。
  • 否则,继续下一个阶段。
(自 C++26 起)

[编辑] 阶段 4

  • 如果任一操作数是 浮点类型,则应用以下规则
  • 如果两个操作数具有相同的类型,则不会执行进一步的转换。
  • 否则,如果一个操作数是非浮点类型,则该操作数将转换为另一个操作数的类型。
  • 否则,如果操作数类型的 浮点转换等级 排序但(自 C++23 起) 不相等,则类型具有较低浮点转换等级的操作数将转换为另一个操作数的类型。
  • 否则,如果操作数类型的浮点转换等级相同,则具有较低 浮点转换子等级 的操作数将转换为另一个操作数的类型。
  • 否则,表达式格式错误。
(自 C++23 起)
  • 否则,两个操作数都是整型,继续下一阶段。

[编辑] 阶段 5

两个操作数都转换为一个公共类型 C。给定类型 T1T2 作为操作数的提升类型(根据整型提升规则),应用以下规则来确定 C

  • 如果 T1T2 是相同的类型,则 C 为该类型。
  • 否则,如果 T1T2 都是有符号整型或都是无符号整型,则 C 是具有更高 整型转换等级 的类型。
  • 否则,T1T2 之间的一个类型是有符号整型 S,另一个类型是无符号整型 U。应用以下规则。
  • 如果 U 的整型转换等级大于或等于 S 的整型转换等级,则 CU
  • 否则,如果 S 可以表示 U 的所有值,则 CS
  • 否则,C 为与 S 相对应的无符号整型。

如果一个操作数是枚举类型,而另一个操作数是不同的枚举类型或浮点类型,则此行为已弃用。

(自 C++20 起)
(直到 C++26)

[编辑] 整型转换等级

每个 整型 都具有一个整型转换等级,定义如下。

  • 除了 charsigned char(如果 char 是有符号的)之外,没有两个有符号整型具有相同的等级,即使它们具有相同的表示。
  • 有符号整型的等级高于任何宽度更小的有符号整型的等级。
  • 以下整型的等级按顺序递减。
  • long long
(自 C++11 起)
  • long
  • int
  • short
  • signed char
  • 任何无符号整型的等级都等于相应有符号整型的等级。
  • 任何标准整型的等级都高于任何具有相同宽度的扩展整型的等级。
(自 C++11 起)
  • bool 的等级低于所有标准整型的等级。
  • 编码字符类型(char , char8_t(自 C++20 起), char16_t, char32_t,(自 C++11 起)wchar_t)的等级等于其 底层类型 的等级,这意味着。
  • char 的等级等于 signed charunsigned char 的等级。
  • char8_t 的等级等于 unsigned char 的等级。
(自 C++20 起)
(自 C++11 起)
  • wchar_t 的等级等于其实现定义的底层类型的等级。
  • 任何扩展有符号整型相对于另一个具有相同宽度的扩展有符号整型的等级是实现定义的,但仍然受确定整型转换等级的其他规则的约束。
(自 C++11 起)
  • 对于所有整型 T1T2T3,如果 T1 的等级高于 T2,而 T2 的等级高于 T3,则 T1 的等级高于 T3

整型转换等级也用于 整型提升 的定义中。

[编辑] 浮点转换等级和子等级

[编辑] 浮点转换等级

每个 浮点类型 都具有一个浮点转换等级,定义如下。

  • 标准浮点类型的等级按顺序递减。
    • long double
    • double
    • float
  • 浮点类型 T 的等级高于任何其值集是 T 的值集的真子集的浮点类型的等级。
  • 两个具有相同值集的扩展浮点类型具有相同的等级。
  • 具有与一个 cv 无限定标准浮点类型完全相同的相同值集的扩展浮点类型具有与该标准浮点类型相同的等级。
  • 具有与多个 cv 无限定标准浮点类型相同的相同值集的扩展浮点类型具有与 double 相同的等级。
(自 C++23 起)


浮点转换子等级

具有相同浮点转换等级的浮点类型按浮点转换子等级排序。子等级在具有相同等级的类型之间形成一个全序。

类型 std::float16_tstd::float32_tstd::float64_tstd::float128_t固定宽度浮点类型)比任何具有相同转换等级的标准浮点类型具有更高的转换子等级。否则,转换子等级顺序是实现定义的。

(自 C++23 起)

[编辑] 使用

浮点转换等级和子等级也用于

(自 C++23 起)

[编辑] 缺陷报告

以下更改行为的缺陷报告被追溯应用于之前发布的 C++ 标准。

DR 应用于 已发布的行为 正确行为
CWG 1642 C++98 通常的算术转换可能涉及左值 首先应用左值到右值转换
CWG 2528 C++20 unsigned char 之间的三个方向比较
unsigned int 是格式错误的,因为
中间的整型提升[1]
根据
提升后的类型确定公共类型,而没有
实际提升操作数[2]
CWG 2892 C++98 当两个操作数都是相同类型
的浮点数时,“不需要
进一步转换”的含义不清楚
更改为“不会进行进一步
转换”
  1. 在解决之前,unsigned char 在阶段 5 开始时被提升为 int,然后它被转换为 unsigned int。但是,后一种转换是窄化,这使得三个方向比较格式错误。
  2. 在解决之后,公共类型仍然是 unsigned int。区别在于 unsigned char 直接转换为 unsigned int,没有中间的整型提升。转换不是窄化的,因此三个方向比较是格式良好的。