【问题标题】:Overflowing of Unsigned Int无符号整数溢出
【发布时间】:2012-02-29 22:06:36
【问题描述】:

unsigned int 溢出时会包含什么?具体来说,我想和两个unsigned ints做一个乘法:乘法完成后unsigned int里面会是什么?

unsigned int someint = 253473829*13482018273;

【问题讨论】:

  • 为什么不试试看你会得到什么?通常,当 unsigned int 溢出时,它会翻转为零。所以UINT_MAX + 5 翻转变成 4。
  • 这将是最大 uint 值与溢出值之间的差异。让我们让它变得简单。假设最大 uint 为 5。您想添加 2 * 4,因此最终值是 3 而不是 8。

标签: c++ integer-overflow unsigned-integer


【解决方案1】:

unsigned 数字不能溢出,而是使用模数的属性环绕。

例如,当unsigned int 为 32 位时,结果将是:(a * b) mod 2^32


正如 CharlesBailey 指出的,253473829*13482018273 可能会在转换之前使用有符号乘法,因此您应该在乘法之前明确说明 unsigned

unsigned int someint = 253473829U * 13482018273U;

【讨论】:

  • 这是标准的一部分吗?
  • @Zhenya 是的,在 C 和 C++ 中。
  • @Ramhound:当然很重要。如果标准没有定义这种行为(就像它没有为有符号整数类型定义),那么你就不能依赖它。
  • @Mr.Anubis:不,只有无符号整数类型。有符号和浮点溢出会产生未定义的行为。
  • 这个答案不一定相关。根据编译器的限制,表达式253473829*13482018273 可能会使用有符号整数运算,这可能会在结果转换为unsigned int 之前溢出。
【解决方案2】:

无符号整数溢出与其有符号对应物不同,表现出明确定义的行为。

价值观基本上是“环绕”的。它是安全的,通常用于倒计时或散列/mod 函数。

【讨论】:

  • 我的意思是作为比较来尝试通过与类似的事物相关来解释它。后来我确实用环绕位来限定我的陈述。啊技术性。
【解决方案3】:

这可能在一定程度上取决于您的编译器。几年前我遇到过类似的错误,有时您会遇到运行时错误,有时它基本上会“包装”回一个非常小的数字,这是由于砍掉最高级别的位并留下剩余部分,即如果它是 32 bit unsigned int,并且您的乘法结果将是一个 34 位数字,它将切断高位 2 位并给您余数。您可能必须在编译器上试一试才能准确查看得到的结果,这可能与使用不同编译器得到的结果不同,特别是如果溢出发生在最终结果在无符号整数的范围。

【讨论】:

  • Unsigned 溢出不依赖于编译器,它被标准化为具有环绕语义。只有 signed 溢出会导致未定义的值,因此可能取决于编译器。
猜你喜欢
  • 2013-04-10
  • 2014-12-09
  • 1970-01-01
  • 1970-01-01
  • 2021-03-28
  • 1970-01-01
  • 2021-03-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多