int16溢出导致无限循环

时间:2018-03-27 20:56:02

标签: c++ int integer-overflow

我们知道,int16_t的最大值为32767,因此以下代码将循环:

for (int16_t i = 0; i < 65535; i++) {
  // infinite loop
}

当我更改代码时,它也会循环:

const int32_t t = 65535;
for (int16_t i = 0; i < t; i++) {
  // infinite loop
}

但是当我把它设为uint32_t而不是int32_t时,它实际上会退出:

const uint32_t t = 65535;
for (int16_t i = 0; i < t; i++) {
  // actually exits
}

这是由于它为我做的一些编译技巧吗?我假设我做比较时:

i < t

对于最新版本,它会为我自动转换?但是我不明白它为什么会在最后一个版本中退出......

1 个答案:

答案 0 :(得分:5)

比较签名类型和无符号类型时,在执行比较之前,签名类型将提升为无符号类型。因此,最后一段代码可以工作。

看看以下程序

#include <iostream>
#include <cstdint>

int main()
{
   const uint32_t t = 65535;
   int16_t i = 32765;
   for (; i < t; i++)
   {
      std::cout << i << ", " << static_cast<uint32_t>(i) << std::endl;
   }
   std::cout << i << ", " << static_cast<uint32_t>(i) << std::endl;
}

及其输出与g ++ 6.4.0

32765, 32765
32766, 32766
32767, 32767
-32768, 4294934528

在整数溢出时,i的值从最大值翻转到最小值。更重要的是,当该号码被提升为uint32_t时,它似乎是一个很大的值。

4294934528uint32_t的二进制表示形式为:

11111111 11111111 10000000 00000000

-32768int16_t的二进制表示形式为:

                  10000000 00000000

虽然我不完全明白将无符号类型的签名类型提升为解释相关性的规则,但似乎存在相关性。