if 语句中的评估 (NSIntegers) Objective-C

Evaluation (NSIntegers) inside if-statement Objective-C

我有疑问,为什么它能正常工作:

NSInteger row = indexPath.row;
NSInteger preloadTrigger = self.nodes.count - 20;
if (row >= preloadTrigger) {
    [self.loader loadNextposts];
}

这不会(只是跳过 if 语句):

if (indexPath.row >= self.nodes.count - 20) {
    [self.loader loadNextposts];
}

self.nodes.count - 20的值为负数时。

然而,当表达式的值为正时,它总是工作正常。

一个非常奇怪的行为,因为我看不出两个表达式的语义差异。

更新: 所以,我决定测试一下:

(lldb) po self.nodes.count - 20
18446744073709551601

(lldb) po preloadTrigger
-15

因为nodes.count是NSUInteger,row是NSInteger。无符号整数 - 20 永远不是负值,但会在您期望它为负值的地方产生一个巨大的正值。

根据 Apple Docs,计数 属性 是 NSUIntegerin objective-C。

当你写:

 NSInteger preloadTrigger = self.nodes.count - 20;

事实上,您正在将 count 转换为 NSInteger 对象,如果 count 不大于 20,则可以有一个负值。

但是当你写的时候:

(indexPath.row >= self.nodes.count - 20)

count 是一个 NSUInteger 对象,从中减去 20 总是会得到一个正数(顺便说一下,这是一个很大的数)。

我会在其他正确答案中添加一些解释。

所以,事情是这样的:

self.nodes.count 是 NSUInteger 类型,在 64 位系统中与 unsigned long int 相同,或者在 32 位系统中与 unsigned int 相同。

文字 20 的类型为 int.

当你形成表达式self.nodes.count - 20时,20是'promoted'到另一个操作数(self.nodes.count)的无符号整数类型,因为它有更宽的范围两者中的。

这是因为,当两个操作数具有不同大小的类型时,较小的被提升为较大的以使它们相等并计算这些项的结果(在硬件中,不同类型的值之间的算术运算是'真正定义 - 位表示不同)。

问题是,无符号整数不能表示负值,换来的是相同位长可以表示更大范围的正值。因此,当 20 大于 self.nodes.count 时,结果 "wraps around" 为一个大的无符号整数。

另一方面,indexPath.row 也是一个无符号整数 (NSUInteger),因此您最终会将相对较小的行值与减法运算的巨大结果进行比较;测试:

if (indexPath.row >= self.nodes.count - 20)

...总是失败(左侧较小)。

如果您先将两个结果都转换为有符号整数,然后 然后 比较这些有符号整数:

NSInteger row = indexPath.row;
NSInteger preloadTrigger = self.nodes.count - 20;
if (row >= preloadTrigger) {

...然后没有 wrapping/underflow 发生,你得到预期的结果。