简体   繁体   English

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

[英]Evaluation (NSIntegers) inside if-statement Objective-C

I am in doubt, why this work correctly: 我对此感到怀疑,为什么它可以正常工作:

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

And this does not (just skips the if-statement): 并且这不会(只是跳过if语句):

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

when the value of self.nodes.count - 20 is negative. self.nodes.count - 20的值self.nodes.count - 20为负时。

However, when the value of the expression is positive, it works fine always. 但是,当表达式的值为正数时,它总是可以正常工作。

A very strange behavior, as I cannot see semantic difference in two expressions. 一种非常奇怪的行为,因为我看不到两个表达式的语义差异。

Update: So, I decided to test it: 更新:因此,我决定对其进行测试:

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

(lldb) po preloadTrigger
-15

According to Apple Docs , count property is a NSUInteger in objective-C. 根据Apple Docs的说法,count属性是Objective-C中的NSUInteger

When you write : 当你写:

 NSInteger preloadTrigger = self.nodes.count - 20;

In fact you are casting count to a NSInteger object, and can have a negative value if count isn't greater than 20. 实际上,您正在将count转换为NSInteger对象,如果count不大于20,则可NSInteger负数。

But when you write : 但是当你写:

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

count is a NSUInteger object, and subtract 20 from it will always lead to a positive number (a huge one by the way). count是一个NSUInteger对象,从中减去20将始终导致一个正数(顺便说一下,这是一个很大的数)。

Because nodes.count is NSUInteger and row is NSInteger. 因为nodes.count是NSUInteger,而行是NSInteger。 Unsigned integer - 20 is never a negative value, but results a huge positive value where you expect it to be negative. 无符号整数-20永远不是负值,但是会在您期望它为负数的情况下产生巨大的正值。

I'll add some explanation to the other, correct answers. 我将在其他正确答案中添加一些解释。

So, here is how it goes: 所以,这是怎么回事:

self.nodes.count is of type NSUInteger, which is the same as unsigned long int in 64 bit systems, or alternatively unsigned int in 32 bit systems. self.nodes.count的类型为NSUInteger,与64位系统中的unsigned long int相同,或者在32位系统中与unsigned int

The literal 20 is of type int . 文字20int类型。

When you form the expression self.nodes.count - 20 , 20 is 'promoted' to the unsigned integer type of the other operand ( self.nodes.count ), because it has the wider range of the two. 当您形成表达式self.nodes.count - 2020被“提升”为另一个操作数( self.nodes.count )的无符号整数类型,因为它的范围更广。

That is because, when both operands have types of different sizes, the smaller one gets promoted to the larger one to make them equal and calculate the result in those terms (in hardware, arithmetical operations between values of different types aren't really defined - the bit representations differ). 这是因为,当两个操作数具有不同大小的类型时,较小的一个将被提升为较大的一个以使其相等,并以这些条件计算结果(在硬件中,不同类型的值之间的算术运算并未真正定义-位表示形式有所不同)。

The problem is that, in exchange for being able to represent a wider range of positive values with the same bit length, unsigned integers can not represent negative values. 问题是,为了能够用相同的位长表示更大范围的正值,无符号整数不能表示负值。 So, when 20 is greater than self.nodes.count , the result "wraps around" to a large, unsigned integer. 因此,当20大于self.nodes.count ,结果将“环绕”为一个大的无符号整数。

On the other hand indexPath.row , too, is an unsigned integer ( NSUInteger ), so you end up comparing the relatively small row value with the huge result of the subtraction operation; 另一方面, indexPath.row也是一个无符号整数( NSUInteger ),因此您最终将比较小的行值与减法运算的巨大结果进行了比较。 the test: 考试:

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

...always fails (the left side is smaller). ...总是失败(左侧较小)。

If you first cast both results to signed integer and then compare those signed integers: 如果首先将两个结果都转换为有符号整数, 然后比较这些有符号整数:

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

...then no wrapping/underflow occurs and you get the expected result. ...然后没有发生换行/下溢,您将获得预期的结果。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM