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

时间:2016-02-08 08:36:27

标签: ios objective-c if-statement conditional nsinteger

我有疑问,为什么这样做正确:

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

3 个答案:

答案 0 :(得分:3)

根据Apple Docs,count属性是目标-C中的NSUInteger

当你写:

 NSInteger preloadTrigger = self.nodes.count - 20;

事实上,您正在向count对象投射NSInteger,如果count不大于20,则可以为负值。

但是当你写:

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

count是一个NSUInteger对象,从中减去20将始终导致一个正数(顺便说一个巨大的数字)。

答案 1 :(得分:2)

因为nodes.count是NSUInteger而行是NSInteger。无符号整数 - 20永远不是负值,但会产生巨大的正值,而您预计它会为负值。

答案 2 :(得分:0)

我会向对方添加一些解释,正确答案。

所以,这是怎么回事:

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

文字20的类型为int

当您构建表达式self.nodes.count - 20时,20被提升并且#39;到另一个操作数(self.nodes.count)的无符号整数类型,因为它具有更宽的范围。

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

问题在于,为了能够表示具有相同位长的更宽范围的正值,无符号整数不能表示负值。因此,当20大于self.nodes.count时,结果"包围"到一个大的无符号整数。

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

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

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

如果你首先将两个结果都转换为有符号整数,那么然后比较那些有符号整数:

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

...然后没有发生包装/下溢,你得到预期的结果。