我在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 位有符号 int 以进行第一次赋值操作,并且 c 仍应获得 16 位 -128 值。我的理解正确吗?C++ 标准有点难以阅读。第 4 章似乎在讨论整数提升,但我找不到与这个特定示例相关的任何内容。

有帮助吗?

解决方案

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

不,促销活动发生在 + 是被评估的,而不是在评估之后。当两者都存在时,就会发生加法 ab 是积极的。两个号码都提升为 ints 进行加法,作为两个正数相加,然后转换为 16 位短整型。在此过程中任何时候结果都不会因溢出而变为负数,因此最终结果为 128。

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

其他提示

就是积分促销。

1 如果 int 可以表示源类型的所有值,则除 bool、char16_t、char32_t 或 wchar_t 之外的整数类型的纯右值(其整数转换等级 (4.13) 小于 int 的等级)可以转换为 int 类型的纯右值;否则,可以将源纯右值转换为 unsigned int 类型的纯右值。[第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 位整数,符号位为 0b1000000000000000 (哪个 a+b 没有),对于 8 位整数,符号位是 0b10000000 (哪个 a+b 确实有)。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top