C ++意外整数提升 [英] C++ Unexpected Integer Promotion

查看:66
本文介绍了C ++意外整数提升的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

最近我正在编写一些本应用于测试其他代码的代码,但我偶然发现了一个令人惊讶的整数提升案例.这是最小的测试用例:

I was writing some code recently that was actually supposed to test other code, and I stumbled upon a surprising case of integer promotion. Here's the minimal testcase:

#include <cstdint>
#include <limits>

int main()
{
    std::uint8_t a, b;
    a = std::numeric_limits<std::uint8_t>::max();
    b = a;

    a = a + 1;

    if (a != b + 1)
        return 1;
    else
        return 0;
}

令人惊讶的是,该程序返回1.一些调试和预感表明条件中的 b + 1 实际上返回了256,而赋值中的 a + 1 产生了预期的结果.值为0.

Surprisingly this program returns 1. Some debugging and a hunch revealed that b + 1 in the conditional was actually returning 256, while a + 1 in assignment produced the expected value of 0.

C ++ 17草案的8.10.6节(关于等式/不等式运算符)声明

Section 8.10.6 (on the equality/ineuqlity operators) of the C++17 draft states that

如果两个操作数均为算术或枚举类型,则通常对两个操作数;如果指定的关系为真,则每个运算符应产生true;如果指定的关系为false,则产生false.错误.

If both operands are of arithmetic or enumeration type, the usual arithmetic conversions are performed on both operands; each of the operators shall yield true if the specified relationship is true and false if it is false.

什么是通常的算术转换"?在标准中它们在哪里定义?我的猜测是,对于某些运算符,它们隐式地将较小的整数提升为 int unsigned int (替换为 std :: uint8_t

What are "the usual arithmetic conversions", and where are they defined in the standard? My guess is that they implicitly promote smaller integers to int or unsigned int for certain operators (which is also supported by the fact that replacing std::uint8_t with unsigned int yields 0, and further in that the assignment operator lacks the "usual arithmetic conversions" clause).

推荐答案

什么是通常的算术转换"?在标准中它们在哪里定义?

What are "the usual arithmetic conversions", and where are they defined in the standard?

[expr.arith.conv]/1

许多期望算术或枚举类型原因转换和收益结果类型类似办法.目的是产生一个通用类型,这也是结果.这种模式称为通常的算术转换,定义如下:

Many binary operators that expect operands of arithmetic or enumeration type cause conversions and yield result types in a similar way. The purpose is to yield a common type, which is also the type of the result. This pattern is called the usual arithmetic conversions, which are defined as follows:

  • (1.1)如果两个操作数中的任何一个是枚举类型,无转化执行;如果另一个操作数不具有相同的类型,则表达式格式错误.

  • (1.1) If either operand is of scoped enumeration type, no conversions are performed; if the other operand does not have the same type, the expression is ill-formed.

(1.2)如果一个操作数的类型为long double,则另一个应为转换为长双.

(1.2) If either operand is of type long double, the other shall be converted to long double.

(1.3)否则,如果其中一个操作数为double,则另一个应为转换为double.

(1.3) Otherwise, if either operand is double, the other shall be converted to double.

(1.4)否则,如果其中一个操作数为浮点型,则另一个应为转换为float.

(1.4) Otherwise, if either operand is float, the other shall be converted to float.

(1.5)否则,积分促销( [conv.prom] )应为 59 则以下规则应为应用于提升的操作数:

(1.5) Otherwise, the integral promotions ([conv.prom]) shall be performed on both operands.59 Then the following rules shall be applied to the promoted operands:

  • (1.5.1)如果两个操作数具有相同的类型,则不再进行转换需要.

  • (1.5.1) If both operands have the same type, no further conversion is needed.

(1.5.2)否则,如果两个操作数都具有符号整数类型或两者都具有无符号整数类型,具有较小类型的操作数整数转换等级应转换为操作数的类型排名更高.

(1.5.2) Otherwise, if both operands have signed integer types or both have unsigned integer types, the operand with the type of lesser integer conversion rank shall be converted to the type of the operand with greater rank.

(1.5.3)否则,如果具有无符号整数类型的操作数具有等级大于或等于另一个类型的等级操作数,带符号整数类型的操作数应转换为具有无符号整数类型的操作数的类型.

(1.5.3) Otherwise, if the operand that has unsigned integer type has rank greater than or equal to the rank of the type of the other operand, the operand with signed integer type shall be converted to the type of the operand with unsigned integer type.

(1.5.4)否则,如果操作数的类型为带符号整数类型可以用无符号整数类型,无符号整数类型的操作数应为转换为带符号整数类型的操作数的类型.

(1.5.4) Otherwise, if the type of the operand with signed integer type can represent all of the values of the type of the operand with unsigned integer type, the operand with unsigned integer type shall be converted to the type of the operand with signed integer type.

(1.5.5)否则,两个操作数均应转换为无符号整数类型,对应于带符号的操作数的类型整数类型.

(1.5.5) Otherwise, both operands shall be converted to the unsigned integer type corresponding to the type of the operand with signed integer type.

59) 因此,类型为bool,char8_t,char16_t,char32_t,wchar_t或枚举类型被转换为某些类型整型.

59) As a consequence, operands of type bool, char8_­t, char16_­t, char32_­t, wchar_­t, or an enumerated type are converted to some integral type.

对于 uint8_t int (稍后针对 operator + operator!= ),应用#1.5, uint8_t 将被提升为 int ,而 operator + 的结果也是 int .

For uint8_t vs int (for operator+ and operator!= later), #1.5 is applied, uint8_t will be promoted to int, and the result of operator+ is int too.

另一方面,对于 unsigned int int (对于 operator + ),适用#1.5.3, int将被转换为 unsigned int ,并且 operator + 的结果是 unsigned int .

On the other hand, for unsigned int vs int (for operator+), #1.5.3 is applied, int will be converted to unsigned int, and the result of operator+ is unsigned int.

这篇关于C ++意外整数提升的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆