【问题标题】:C++ Arithmetic With Mixed Integral Types That Causes Overflow具有导致溢出的混合积分类型的 C++ 算术
【发布时间】:2013-11-17 13:40:46
【问题描述】:

我在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 章似乎在谈论整数提升,但我找不到与这个特定示例相关的任何内容。

【问题讨论】:

  • 积分提升正是通过通常的算术转换发生的;见 [expr]/10。

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


【解决方案1】:

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

不,促销发生在评估 + 之前,而不是之后。当ab 都是正数时,会发生加法。这两个数字都提升为ints 进行加法,作为两个正数相加,然后转换为 16 位短整数。在此过程中,结果不会因溢出而变为负数,因此最终结果为 128。

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

【讨论】:

    【解决方案2】:

    是整体推广。

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

    在此声明中

     __int16 c=b+a;
    

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

    变量ba 将提升为int,然后对它们进行操作。

    【讨论】:

      【解决方案3】:

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-05-15
        • 2011-07-15
        • 2011-05-11
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多