所以,如果您尝试评估无符号整数< 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?
答案 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
(假设numb
为unsigned long
)。此外,unsigned long
的定义的一部分是,当您为其指定超出范围的值时,该值将以模ULONG_MAX + 1
为模,直到它进入范围。所以代码也等同于:
numb == ULONG_MAX
这就是您在0
之后看到的第一个输出是ULONG_MAX
。
答案 2 :(得分:0)
从技术上讲,您的号码永远不会等于-1
。将无符号数与签名 -1
进行比较时,最后一个也会转换为无符号数,因此产生的值等于testInt
。
unsigned
与0
的比较以及主要使用less运算符仍然总是错误的,因为0
是无符号的,因此没有从一种数据类型到另一种数据类型的提升#39; t发生。