代码之家  ›  专栏  ›  技术社区  ›  WhatABeautifulWorld

int16溢出导致无限循环

  •  1
  • WhatABeautifulWorld  · 技术社区  · 6 年前

    正如我们所知,int16\u 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\u t而不是int32\u t时,它实际上会退出:

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

    这是因为它为我带来了一些编译器技巧吗?我假设在进行比较时:

    i < t
    

    对于上一个版本,它会为我自动转换吗?但我不明白为什么它在最后一个版本中仍然存在。。。

    1 回复  |  直到 6 年前
        1
  •  5
  •   R Sahu    6 年前

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


    看看下面的程序

    #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 ,它似乎是一个很大的值。

    的二进制表示 4294934528 在里面 uint32\u t 是:

    11111111 11111111 10000000 00000000
    

    的二进制表示 -32768 在里面 int16_t 是:

                      10000000 00000000
    

    虽然我不完全理解将有符号类型提升为无符号类型的规则是什么来解释这种相关性,但这里似乎存在相关性。