C++中无符号字符溢出

Overflow of an unsigned char in C++

本文关键字:溢出 字符 无符号 C++      更新时间:2023-10-16

我在这里找到了以下代码片段https://www.toptal.com/c-plus-plus/interview-questions问题是:这个循环将执行多少次?解释您的答案

unsigned char half_limit = 150;
for (unsigned char i = 0; i < 2 * half_limit; ++i)
{
// do something;
}

答案是无限的。

表达式2*half_limit将被提升为int(基于C++转换规则(,并且将具有值300。然而,由于我是一个无符号字符,它由一个8位值重新读取,在达到255将溢出(因此将返回到0(,并且循环因此将永远持续下去。

我猜了45次(300-255(,因为我记得如果你增加一个无符号整数计数器,当它溢出时,计数器将再次从0开始。好吧,它从一个整数转换为一个无符号字符,为什么不是255呢?

谢谢

为什么不是255?

因为255小于300。在下一次迭代中,i将为0,也小于300。用8位整数表示的数字都不能达到300。


从技术上讲,正确的答案是迭代次数取决于unsigned char的大小。在使用16位字节的系统上,不会有任何问题。

答案的另一个问题是,除非在循环中采取某些操作,例如生成一些输出,否则语言中不允许"无限"循环。因此,实际上,示例程序具有未定义的行为(假设为8位字节(。报价来源标准:

[intro.progress]

实现可能假设任何线程最终都会执行一个以下内容之一:

  • 终止
  • 调用库I/O函数
  • 通过易失性glvalue执行访问,或者
  • 执行同步操作或原子操作

[注意:这是为了允许编译器转换,例如删除空环路,即使在无法证明终止的情况下也是如此。——终止注]

小于int的类型上的算术首先将它们提升为int。因此CCD_ 5就是CCD_。假设unsigned char所能代表的最大值是255,则所有的值i都可能满足i < 2 * half_limit,因此这是一个无限循环。

2 * half_limit

与相同

int(2) * int(half_limit)

half_limit被提升为一个整数来进行乘法运算,表达式的结果是300。因此,

i < 2 * half_limit

成为

i < int(300)

其中,我被提升为int来进行实际比较,但由于我是一个无符号字符,它永远不会大于255(假设我们的无符号字符是8位(,因此比较有效:

int(smaller than 256) < int(300)

当然,这总是正确的。

#include <iostream>
int main(int argc,char* argv[]){
unsigned char half_limit = 150;
for (unsigned char i = 0; i < 2 * half_limit; ++i)
{
printf("%.2Xn", i);
}
}

用mingw g++编译了这段代码。给了我一个无限循环,打印出了十六进制i的值表明它每次溢出时都会被重置。也许当它溢出时会设置一个标志。。如果错误,请纠正我