C++具有导致溢出的混合整数类型的算术

C++ Arithmetic With Mixed Integral Types That Causes Overflow

本文关键字:混合 整数 类型 溢出 C++      更新时间:2023-10-16

我在VC++2010中做了一些测试,混合了不同大小的操作数,导致添加操作溢出:

int _tmain(int argc, _TCHAR* argv[])
{
    __int8 a=127;
    __int8 b=1;
    __int16 c=b+a;
    __int8  d=b+a;
    printf("c=%d,d=%dn",c,d);
    return 0;
}
//result is: c=128, d=-128

我不明白为什么c==128! 我的理解是,在这两个加法中,b+a 仍然被认为是 2 个有符号 8 位变量的加法。所以结果是溢出,即 -128。 之后,对于第一次赋值操作,结果将提升为 16 位有符号 int,c 仍应获得 16 位 -128 值。 我的理解正确吗? c++标准有点难以阅读。第 4 章似乎在谈论整数提升,但我找不到与此特定示例相关的任何内容。

我的理解是,在这两个加法中,b+a 仍然被认为是 2 个有符号 8 位变量的加法。所以结果是溢出,即 -128。

不,促销发生在评估+之前,而不是之后。当ab均为正时,就会发生加法。两个数字都提升到 int s 以进行加法,作为两个正数相加,然后转换为 16 位短数。在过程中的任何一点,结果都不会因溢出而变为负数,因此最终结果为 128。

可以说,这是有道理的:ab的行为与数学中两个数字的行为相匹配,使语言从业者更直观。

这是不可或缺的推广。

1 如果整数转换秩 (4.13) 小于 int 的整数类型,则 bool、char16_t、char32_t 或 wchar_t 以外的整数类型的 prvalue 可以转换为 int 类型的 prvalue,如果 int 可以表示源类型的所有值;否则,源 prvalue 可以转换为无符号 int 类型的 prvalue。 [§ 4.5]

在此声明中

 __int16 c=b+a;

首先,所有charshort int值都会自动提升为 int 。这个过程称为整体提升。接下来,将所有操作数转换为最大操作数的类型,这称为类型提升。[赫伯特·希尔德]

变量 ba 的值将提升为 int,然后对它们应用操作。

在二进制补码整数表示中,有符号值通过设置最高位来表示。 这允许机器使用相同的指令加减二进制整数,而不管整数是否有符号。

  a = 127 == 0x7F == 0b01111111
+ b =   1 == 0x01 == 0b00000001
-------------------------------
  c = 128 == 0x80 == 0b10000000
  d =-128 == 0x80 == 0b10000000

变量cd可能具有不同的类型,但不同类型的整数只是对单个二进制值的不同解释。 正如您在上面看到的,二进制值适合 8 位就好了。 由于该标准要求数学表达式的项在完成任何数学运算之前为零或符号扩展(提升)到机器字的大小,并且两个操作数都不会进行符号扩展,因此无论操作数是什么类型,结果始终是0b10000000的。

总之,结果之间的区别在于,对于 16 位整数,符号位是0b1000000000000000a+b没有),而对于 8 位整数,符号位是0b10000000a+b确实有)。