Evaluation (NSIntegers) inside if-statement Objective-C

萝らか妹 提交于 2019-12-06 11:30:54

问题


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 (indexPath.row >= self.nodes.count - 20) {
    [self.loader loadNextposts];
}

when the value of self.nodes.count - 20 is negative.

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

回答1:


According to Apple Docs, count property is a NSUIntegerin objective-C.

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.

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).




回答2:


Because nodes.count is NSUInteger and row is NSInteger. Unsigned integer - 20 is never a negative value, but results a huge positive value where you expect it to be negative.




回答3:


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.

The literal 20 is of type int.

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.

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.

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; 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.



来源:https://stackoverflow.com/questions/35265279/evaluation-nsintegers-inside-if-statement-objective-c

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!