for (unsigned char i = 0; i<=0xff; i++) 产生无限循环

for (unsigned char i = 0; i<=0xff; i++) produces infinite loop

为什么下面的 c 代码会陷入死循环?

for(unsigned char i = 0; i <= 0xff; i++){}

结果相同:

for(unsigned char i = 0; i <= 0xff; ++i){}

我必须以何种方式修改代码,使其按预期工作(不使用 intunsigned int 数据类型)?

因为你环绕。一个 unsigned char 值的范围在 0-255 之间,并且因为 unsigned 算术是很好定义的,你实际上将 i 的值包装到 0 并且条件仍然满足并且迭代继续无限。

在有符号值的情况下,它是未定义的行为,存储在 i 中的值可能不是 0。但它仍然会小于您可以存储在 char 中的最大值并且仍然满足条件。

unsigned char 的范围是 0 到 255 (0xff)。将 1 加到 0xff 得到 0x100,当它被分配回一个 unsigned char 时又回到 0.

因此比较 i <= 0xff 将始终为真。因此无限循环。

如果希望循环在 0xff 之后停止,请使用 int 作为数据类型。这个范围至少是 -32767 到 32767,通常更多。

如果你真的需要使用unsigned char那么你可以使用

unsigned char i = 0;
do {
    // ... 
} while(++i);

当对 unsigned 整数的算术运算超出其限制时,行为已明确定义。所以这个解决方案将处理 256 个值(对于 8 位 unsigned char)。

典型的 for 循环依赖于能够在循环的最后一次迭代 之后检测到终止条件 。在您的情况下,正如其他答案所指出的那样,i <= 0xff 始终为真(假设 i 属于 unsigned char 类型并且 UCHAR_MAX==0xff 是典型的类型)。

您可以运行解决任何整数类型边界附近的同类问题。例如,这个:

for (int i = INT_MAX - 9; i <= INT_MAX; i ++) {
    /* ... */
}

(可能)也是一个无限循环(除了有符号整数类型的溢出具有未定义的行为,与无符号整数的明确定义的环绕语义相反,优化编译器可以利用它并且 - 但是我离题了)。只是不要那样做。

许多解决方案之一是将测试移动到循环的底部,在增量之前:

for (unsigned char i = 0; ; i ++) {
    printf("%d\n", i);
    if (i == 0xff) break;
}

for 循环的第二个子句是终止条件,在每次迭代之前计算。如果您将它留空,它会被视为始终为真,从而给您一个无限循环(for (;;) 是简单无限循环的常见用法)。我们在循环底部测试 i 是否 等于 0xff。如果是,那么我们刚刚执行了最后一次迭代,我们可以跳出循环。

(有些人可能更喜欢在这里使用 while 循环,但我喜欢 for 因为它让我们可以将循环控制变量的声明和增量组合在一个构造中。)

(严格来说 unsigned char 的最大值不一定是 0xff255,但它会出现在您可能遇到的任何系统上。一些实现DSP 有 CHAR_BIT > 8,因此 UCHAR_MAX > 255。)