【问题标题】:Kinds of integer overflow on subtraction减法整数溢出的种类
【发布时间】:2010-10-20 22:16:59
【问题描述】:

我正在尝试重新学习 C++,使用 Sams Teach Yourself C++ in 21 Days(第 6 版)。我正在尝试非常彻底地完成它,确保我理解每一章(尽管我已经熟悉 C 语法语言)。

在第 5 章的开头(清单 5.2)附近,有一点是关于无符号整数溢出的。根据他们的例子,我写了这个:

#include <iostream>

int main () {
    unsigned int bignum = 100;
    unsigned int smallnum = 50;
    unsigned int udiff;
    int diff;
    udiff = bignum - smallnum;
    std::cout << "Difference (1) is " << udiff << "\n";
    udiff = smallnum - bignum;
    std::cout << "Difference (2) is " << udiff << "\n";
    diff = bignum - smallnum;
    std::cout << "Difference (3) is " << diff << "\n";
    diff = smallnum - bignum;
    std::cout << "Difference (4) is " << diff << "\n";
    return 0;
}

这给出了以下输出,这对我来说并不奇怪:

Difference (1) is 50
Difference (2) is 4294967246
Difference (3) is 50
Difference (4) is -50

如果我更改程序以便声明bignum 的行改为unsigned int bignum = 3000000000;,则输出改为

Difference (1) is 2999999950
Difference (2) is 1294967346
Difference (3) is -1294967346
Difference (4) is 1294967346

其中第一个显然很好。 1294967346 这个数字可以通过1294967346 恰好是2^32 - 3000000000 这一事实来解释。我不明白为什么第二行不写1294967396,因为smallnum贡献了50。

第三行和第四行我无法解释。这些结果是如何产生的?

编辑:对于第三行 - 它是否仅通过找到适合有符号 int 允许的值范围的解模 2^32 来给出此结果?

【问题讨论】:

  • 检查你的算术,2^32 = 4294967296

标签: c++ integer integer-overflow


【解决方案1】:

2^32 - 3000000000 = 1294967296 (!)

【讨论】:

  • 2^32 - 3000000000 比 1294967296 阶乘小很多。
  • 是的,你是对的。你能告诉我第三个是怎么发生的吗?
  • 第三个是技术实现定义的。但实际上,在二进制补码架构上,bignum - smallnum 的计算结果为 2999999950。然后将其分配给signed int,这将基本上重新解释底层位而不修改它们。这导致 -1294967346。 C 标准说 “[如果] 新类型是有符号的,并且值不能在其中表示;结果是实现定义的,或者引发了实现定义的信号”.
猜你喜欢
  • 1970-01-01
  • 2015-03-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-21
  • 2011-11-24
  • 2020-06-12
  • 2014-01-24
相关资源
最近更新 更多