为什么在C语言中使用无符号整型倒计时会导致无限循环?

5
以下代码运行时会陷入无限循环。 'i'已被初始化为1并与0进行比较。
因此,printf()语句应该只执行一次,但它却无限循环地运行。
unsigned int i = 1;
for (; i >= 0; i--) {
    printf("Hello: %u\n",i);
}

请解释这种行为。

你能展示一下你的代码吗?这可能是内存损坏,或者是某个函数参数的缓冲区溢出。 - Sergey Kucher
@Sergey:我认为你是错的——这只是一个错误。请看答案。 - RichieHindle
你的循环条件正在等待一个无符号整数变为负数...这怎么可能甚至发生呢? - Yanick Rochon
5个回答

10

因为 iunsigned 类型,所以它不可能变成负数,因此 i>=0 总是为真。

i 为零时,执行 i--i 的值会被回绕到一个 unsigned int 可以达到的最大值(大于零)。

您应该通过删除 unsigned 修饰符来使用有符号整数。


感谢Ritchie让我理解了。 - Angus

9

正如其他答案所说,这是因为它是无符号的。我将告诉您一种优雅的方式,用无符号整数实现您想要做的事情

unsigned int i=10;
while(i --> 0) printf("Hello:%u\n", i+1);

这个 --> 有时被称为箭头操作符。但实际上它只是 -->。如果你改变间距,你会得到:

while( i-- > 0 )

我的意见


它偶尔可能被称为那样。但这是一个有点傻的名字!它只会向下“走”。 - Oliver Charlesworth
@Oli:下降到听起来更好吗? :) - Armen Tsirunyan
7
除非你的目的是混淆,否则请将其写为(while i-- > 0) - Keith Thompson
1
@Keith:我认为i --> 0并不是混淆的。说实话,对我来说比i-- > 0更自然。 - Armen Tsirunyan
5
对于不熟悉的读者来说,这会暗示这种语言有一个“-->”操作符。 - Keith Thompson
显示剩余2条评论

3

这是一个无符号整数unsigned int。从0开始递减它不会得到-1。

为了达到您的预期目标,您需要去掉unsigned限定词。这将纠正引起观察到的行为的整数溢出问题。


你链接的文章正确地指出,对于无符号整数模包装是定义行为,术语溢出从不适用:“涉及无符号操作数的计算永远不会溢出。” - Antti Haapala -- Слава Україні
@AnttiHaapala 确实如此。 - Linus Kleen

1

标准规定,对于无符号整数,如果结果小于零,则需要添加2的n次方,其中n是表示中的位数。

由于整数是无符号的,编译器将优化为无限循环。


优化与此无关。它已经是一个无限循环了。 - Keith Thompson
我的意思是它移除了条件检查。 - Karoly Horvath
好的 - 但并不需要这样做。 - Keith Thompson
你是同意还是不同意? - Keith Thompson

1
通过将i定义为无符号整数,您使其成为始终非负的整数,因此i可以有的所有可能值都是正整数(在其范围内)和0。因此,循环中的条件始终为真,因为i始终大于或等于0,因此它会无限运行。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接