为什么是无符号表达式的比较< 0总是假的

时间:2014-04-05 23:48:11

标签: c++ objective-c c

所以,如果您尝试评估无符号整数< 0,你收到一条警告说:

  

无符号表达式的比较< 0总是假的

这是因为无符号整数在技术上从来都不是负数,这是我到目前为止找到的最佳解释:here

但如果我运行这样的事情:

for (int i = 0; i < 10; i++) {
    testInt--;
    NSLog(@"TestInt = %li", testInt);

    // WARNING AREA //
    if (testInt < 0) {
        NSLog(@"HI");
    }

    // OK //
    if (testInt == -1) {
        NSLog(@"Negative ...");
    }
}

我会得到输出:

  

TestInt = 4

     

TestInt = 3

     

TestInt = 2

     

TestInt = 1

     

TestInt = 0

     

TestInt = -1

     

否定......

     

TestInt = -2

     

TestInt = -3

     

TestInt = -4

     

TestInt = -5

您可以看到该数字对负值的评估正常,并且可以等于-1。

更新

在@ RobP的回答之后,我注意到我的日志记录存在问题,它应该是%lu,它给出了输出:

  

TestInt = 4

     

TestInt = 3

     

TestInt = 2

     

TestInt = 1

     

TestInt = 0

     

TestInt = 18446744073709551615

     

否定......

     

TestInt = 18446744073709551614

     

TestInt = 18446744073709551613

     

TestInt = 18446744073709551612

     

TestInt = 18446744073709551611

但是,我的问题仍然存在,因为它仍然可以评估numb == -1而不是numb < 0

问题

为什么NSUInteger可以同时等于-1但不小于0?

3 个答案:

答案 0 :(得分:2)

问题在于您显示的是数字,而不是数字。这一行:

NSLog(@"TestInt = %li", testInt);

取无符号整数并将其显示为带符号的int。将格式说明符更改为%lu,您应该看到您的值“真正”到机器上。

编辑: 感谢Massa在下面评论比较的平等性。当您将无符号变量与有符号值-1进行比较时,-1会变为无符号值(通常是无符号整数的最大值)并且它们相等,就像将无符号整数等于0并减去1时一样,它变成了UINT_MAX。

答案 1 :(得分:1)

关于它没有“技术上”。无符号整数从不为负,完全停止。他们要么持有0,要么持有正值。这不需要任何进一步的解释。

如果他们最初是从签名值或类似的东西中分配的,那么他们就不会“记住”。

正如您所发现的,您的原始代码通过使用printf的错误格式说明符导致了未定义的行为。所有这些告诉你(充其量)用于存储此unsigned int的位与用于存储特定signed int的位相同。但是这些位的含义是不同的,这就是数据类型的作用:它们告诉我们应该如何将某组位解释为值。

在代码numb == -1中,存在问题。您在两种不同的数据类型上使用==。例如,在Java中,编译器完全拒绝这一点。但是,在C和C ++中,有一些称为隐式转换的规则将猜测您最有可能尝试做什么,并对其中一个操作数执行转换以匹配另一个操作数。

在这种特殊情况下,规则是如果一个操作数具有类型signed T而另一个unsigned T,则签名的操作数将被赋予无符号。所以你的代码实际上就像:

numb == (unsigned long)-1

(假设numbunsigned long)。此外,unsigned long的定义的一部分是,当您为其指定超出范围的值时,该值将以模ULONG_MAX + 1为模,直到它进入范围。所以代码也等同于:

numb == ULONG_MAX

这就是您在0之后看到的第一个输出是ULONG_MAX

答案 2 :(得分:0)

从技术上讲,您的号码永远不会等于-1。将无符号数与签名 -1进行比较时,最后一个也会转换为无符号数,因此产生的值等于testInt

unsigned0的比较以及主要使用less运算符仍然总是错误的,因为0是无符号的,因此没有从一种数据类型到另一种数据类型的提升#39; t发生。