我在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章似乎在谈论整体推广,但我找不到与这个具体例子相关的任何内容。
答案 0 :(得分:2)
我的理解是,在两个添加中,b + a仍然被认为是添加了2个带符号的8位变量。结果是溢出,即-128。
不,促销发生在评估+
之前,而不是之后。当a
和b
均为正数时,就会发生添加。这两个数字都被提升为int
s以进行添加,添加为两个正数,然后转换为16位短数。在此过程中,由于溢出,结果不会变为负值,因此最终结果为128。
可以说,这是有道理的:a
和b
的行为与数学中两个数字的行为相匹配,使语言从业者更直观。
答案 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;
首先,所有
char
和short int
值都会自动提升为int
。此过程称为整体促销。接下来,所有操作数都将转换为最大操作数的类型,称为类型提升。 [Herbert Schildt]
变量b
和a
的值将被提升为int
,然后该操作适用于它们。
答案 2 :(得分:0)
在二进制补码整数表示中,通过设置最高位来表示有符号值。这允许机器使用相同的指令添加和减去二进制整数,无论整数是否已签名。
a = 127 == 0x7F == 0b01111111
+ b = 1 == 0x01 == 0b00000001
-------------------------------
c = 128 == 0x80 == 0b10000000
d =-128 == 0x80 == 0b10000000
变量c
和d
可能有不同的类型,但不同类型的整数只是单个二进制值的不同解释。如上所示,二进制值恰好适合8位。由于标准要求数学表达式的项在零<或符号扩展(提升)到机器字的大小之前任何数学运算完成,并且两个操作数都不会进行符号扩展,结果无论操作数是什么类型,总是0b10000000
。
总之,结果之间的区别在于,对于16位整数,符号位为0b1000000000000000
(a+b
没有),对于8位整数,符号位是0b10000000
(a+b
确实有。)