导致溢出的混合积分类型的C ++算法

时间:2013-11-17 13:40:47

标签: c++ integer-overflow type-promotion

我在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=%d\n",c,d);

    return 0;
}

//result is: c=128, d=-128

我不明白为什么c == 128!我的理解是,在两个添加中,b + a仍然被认为是添加了2个带符号的 8位变量。结果是溢出,即-128。 之后,然后将结果提升为第一个赋值操作的16位signed int,并且c仍应获得16位-128值。我的理解是否正确? c ++标准有点难以阅读。第4章似乎在谈论整体推广,但我找不到与这个具体例子相关的任何内容。

3 个答案:

答案 0 :(得分:2)

  

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

不,促销发生在评估+之前,而不是之后。当ab均为正数时,就会发生添加。这两个数字都被提升为int s以进行添加,添加为两个正数,然后转换为16位短数。在此过程中,由于溢出,结果不会变为负值,因此最终结果为128。

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

答案 1 :(得分:1)

这是不可或缺的推广。

  

1 除了bool,char16_t,char32_t或wchar_t之外的整数类型的prvalue,其整数转换等级(4.13)小于int的等级,可以转换为int类型的prvalue如果int可以表示源类型的所有值;否则,源prvalue可以转换为unsigned int类型的prvalue。 [§4.5]

在本声明中

 __int16 c=b+a;
  

首先,所有charshort int值都会自动提升为int。此过程称为整体促销。接下来,所有操作数都将转换为最大操作数的类型,称为类型提升。 [Herbert Schildt]

变量ba将被提升为int,然后该操作适用于它们。

答案 2 :(得分:0)

在二进制补码整数表示中,通过设置最高位来表示有符号值。这允许机器使用相同的指令添加和减去二进制整数,无论​​整数是否已签名。

  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确实有。)