当前位置: 首页 > 知识库问答 >
问题:

了解非重载位运算符的转换、算术转换和整数提升的顺序

曾鸿振
2023-03-14

我想确切地了解当编译器遇到非重载运算符时发生了什么,以及操作了哪些转换。作为一个例子,让我们以按位运算符为例,例如

[expr.bit.and]执行通常的算术转换;结果是操作数的按位AND函数。运算符仅适用于整数或无作用域的枚举操作数。

然后,如果我正在搜索通常的算术转换,我得到:

[expr]许多期望操作数为算术或枚举类型的二进制运算符会导致转换,并以类似的方式生成结果类型。目的是生成一个公共类型,它也是结果的类型。此模式称为常用算术转换,其定义如下:

  • 如果任一操作数为作用域枚举类型(7.2),则不执行任何转换;如果另一个操作数的类型不同,则表达式的格式不正确

现在,如果我们看整数提升:

[conv.prom]:

  • 整数转换秩小于int秩的整数类型(bool、char16_t、char32_t或wchar_t除外)的prvalue可以转换为int类型的prvalue,如果int可以表示源类型的所有值;否则源prvalue可以转换为无符号int类型的prvalue。
  • 类型char16_t、char32_t或wchar_t(3.9.1)的prvalue可以转换为以下第一种类型的prvalue,这些类型可以表示其基础类型的所有值:int、un符号int、long int、un符号long int、long long int,或无符号的long long int。如果该列表中的任何类型都不能表示其基础类型的所有值,则char16_t、char32_t或wchar_t类型的prvalue可以转换为其基础类型的prvalue。
  • 未限定范围的枚举类型(其基础类型不是固定的)的prvalue可以转换为以下类型中第一种的prvalue,该类型可以表示枚举的所有值:int、无符号int、long int、无符号long int、long longint,或无符号long int。如果该列表中的任何类型都不能表示枚举的所有值,则未限定范围的枚举类型的prvalue可以转换为扩展整数类型的prvalue,其最低整数转换秩大于long long的秩,其中所有可以表示枚举的值。如果有两个这样的扩展类型,则选择签名类型。
  • 其基础类型固定的未限定范围的枚举类型的prvalue可以转换为其基础类型的prvalue。此外,如果可以将积分提升应用于其基础类型,则其基础类型是固定的未限定范围枚举类型的prvalue也可以转换为提升的基础类型的prvalue。
  • 如果int可以表示整数位域的所有值,则整数位域的prvalue可以转换为int类型的prvalue;否则,如果无符号int可以表示位域的所有值,则可以转换为无符号int领域。如果位域更大,则不会对其进行积分提升。如果位字段具有枚举类型,则出于推广目的,它将被视为该类型的任何其他值。
  • bool类型的prvalue可以转换为int类型的prvalue,false变为0,true变为1。
  • 这些转换称为积分提升。

但是如果我们这样做了:

std::integral_constant<int, 2> x;
std::integral_constant<int, 3> y;
int z = x & y;

它会起作用,尽管我没有看到标准中规定了它的位置。我想确切地说,所有的转换检查都在订单中完成。我认为首先,编译器检查运算符是否

那么,编译器在进行哪些转换测试和步骤,以及在遇到T1时的顺序是什么


共有1个答案

印季
2023-03-14

当编译器看到以下情况时:

int z = x & y;

它将看到没有特定的操作符

不需要或不执行算术转换或积分升级。

[conv](2.1)表示:

当用作运算符的操作数时。运算符对其操作数的要求决定了目标类型。

[over.match]说:

这些上下文中的每一个都以自己独特的方式定义候选函数集和参数列表。但是,一旦确定了候选函数和参数列表,在所有情况下,最佳函数的选择都是相同的:

  • (2.8)-首先,选择候选函数的子集(那些具有适当数量的参数并满足某些其他条件的函数)以形成一组可行的函数(13.3.2)。
  • (2.9)-然后根据将每个参数匹配到每个可行函数的相应参数所需的隐式转换序列(13.3.3.1)选择最佳可行函数。

[class.conv]说:

类对象的类型转换可以由构造函数和转换函数指定。这些转换称为用户定义转换,用于隐式类型转换(第4条)、初始化(8.5)和显式类型转换(5.4、5.2.9)。

 类似资料:
  • 我们需要将Javascript散列算法转换为Perl代码。因此,我们需要将JavaScript的按位移位操作符<<、>>和>>>转换为Perl。到目前为止,我们已经有了进行转换的算法,但是由于Javascript按位移位操作符对32位整数进行操作,我们还需要在Perl中模拟这一点。 根据这篇文章https://stackoverflow.com/a/41610348,我们了解到我们可以在Pytho

  • 问题内容: 给定以下JavaScript“类”定义,这是我想到此问题的最佳方式: 以及以下测试设置代码: 有什么方法可以使用加法运算符隐式创建为对象,如下所示… 而不是求助于… 如果不是,那么在此领域中关于通过算术运算符使自定义数字JavaScript对象可组合的最佳实践建议是什么? 问题答案: 据我所知,JavaScript(至少现在已经存在)不支持运算符重载。 我能建议的最好的方法是使用一个类

  • 下面的代码将泛型(POD)类型包装成(模板)类,并定义内部模板转换操作符,以便能够在兼容(但不同)类型之间进行隐式转换。我希望代码是相当自我解释的。在任何情况下,我都无法理解为什么将转换为另一个POD都能正常工作,但将(此处键入为)转换为)却失败得很 有什么想法吗?代码如下:

  • C++ 运算符 强制转换运算符是一种特殊的运算符,它把一种数据类型转换为另一种数据类型。强制转换运算符是一元运算符,它的优先级与其他一元运算符相同。 大多数的 C++ 编译器都支持大部分通用的强制转换运算符: (type) expression 其中,type 是转换后的数据类型。下面列出了 C++ 支持的其他几种强制转换运算符: const_cast<type> (expr): const

  • 问题内容: 我发现Java编译对于使用int和float的赋值和自赋值语句具有非预期的行为。 以下代码块说明了该错误。 在自赋值中,编译不会发出错误,但是求和的结果是带有值的int ,并且变量保持值。 在表达式中,编译器会发出一条错误消息 “错误:可能丢失精度” 。 有人可以解释这种行为。 编辑:我已经将此代码块发布在https://compilr.com/cguedes/java-autoass

  • 问题内容: 我很难理解一些代码,这些代码显示了一个示例,该示例如何将Java中的double转换为byte [],反之亦然。 这是用于将双精度型转换为byte []的代码: 这是用于将byte []转换为double的代码: 好的,这是我不太了解的部分。 似乎强制转换发生在实际的按位运算之前,因为作者说 该表达式将把字节放在长[…]处,然后应用mask删除java施加的符号 在实际转换之前,如何将