4

Consider this C code:

#include "stdio.h"

int main(void) {

    int count = 5;
    unsigned int i;

    for (i = count; i > -1; i--) {
        printf("%d\n", i);
    }
    return 0;
}

My observation/question: the loop never gets executed. But if I change the data type of i from unsigned int to int, everything works as expected.

I've been thinking of unsigned ints as values that "wrap around" when you try to keep subtracting from them. So, when i is zero and I subtract 1, it would wrap around to UINT_MAX. And since its value is never negative, this would be effectively an endless loop. (And this is exactly what happens when I change the comparison from i > -1 to i >= 0.)

There is a fault somewhere in my logic, as the loop never gets executed if i is unsigned, and I'm comparing it to -1. Either the compiler optimizes it away somehow or the runtime values behave differently from what I expect.

Why does the loop not get run?

4

4 回答 4

19

i > -1中,-1 被转换为unsigned int,从而得到值UINT_MAXi永远不会大于该值,因此循环体永远不会执行。

您可能会发现您可以说服编译器警告您:在条件上下文中使用始终为真或始终为假的表达式。但是,如果您编写了 ,那仍然对您没有帮助i > -2,因此您可能还会发现您可以为所有混合符号比较启用警告。

请注意,在 C 中,算术总是使用相同类型的操作数执行。这包括比较,但 IIRC 不包括移位运算符。如果操作数的类型不同,如本例所示,则至少将其中一个转换为相同类型。计算目标类型的规则在 6.3.1.1/2 和 6.3.1.8/1 中。

于 2011-06-02T17:16:17.137 回答
3

+当您在“类型对称”二元运算(例如,*或在您的示例中)中混合具有相同宽度的有符号和无符号操作数时>,无符号类型“获胜”并且该操作在无符号域中进行评估。即有符号操作数被转换为无符号类型。

在您的示例中,整数常量具有 type signed int,而i具有 type unsigned int。操作数具有相同的宽度,因此在您的示例i > -1中被解释为i > (unsigned) -1,相当于i > UINT_MAX. 这就是为什么您的循环永远不会执行的原因。

于 2011-06-02T17:17:42.840 回答
0

-1 成为UINT_MAX无符号比较。由于没有数字大于该值,因此循环条件永远不会为真,并且永远不会进入循环。

如果将其更改为i >= 0,那应该可以按预期工作。实际上,在这种情况下,您可能不应该使用 unsigned :-)

于 2011-06-02T17:17:53.313 回答
0

无论您处理的是无符号数还是有符号数,-1 都将始终编译为 0xffffffff。处理器具有有符号和无符号比较标志。当将该数字与 5 进行比较时,有符号标志会将其视为 -1 并表示它较小,但无符号标志会将其视为一个大数并表示它较大。由于该数字也与 UINT_MAX 相同,因此对于所有无符号数字,您的比较都是错误的。

于 2011-06-02T17:22:23.443 回答