Reputation: 4271
In part of my code I was writing a simple for
loop to iterate over elements in an array (all NSMutableDictionary
s), and I found out the loop executed even if the condition was basically 1 < -1.
So I wrote the following code, to test the validity of this issue:
NSMutableArray* arr = [[NSMutableArray alloc] init];
NSLog(@"COUNT: %d | %i", arr.count, 1 < (arr.count - 1));
The output was:
COUNT: 0 | 1
Which essentially means the count is 0, and that 1 is less than -1.
I thought maybe it's because the array is freshly initialized, and maybe adding and removing an object might change this a bit so I went on to do this:
NSMutableArray* arr = [[NSMutableArray alloc] init];
[arr addObject:@1];
[arr removeObject:@1];
NSLog(@"COUNT: %d | %i", arr.count, 1 < (arr.count - 1));
Still same result:
COUNT: 0 | 1
The possible reasons that come to my mind for this:
I highly doubt that it's either of the last 2 cases, still I'd like to know why this is happening.
Upvotes: 0
Views: 146
Reputation: 82535
arr.count
is an unsigned integer value (of type NSUInteger
). With unsigned arithmetic, (0 - 1)
wraps around to a very large positive number, not -1
.
You may see the results you expect if you cast the values to signed integers:
NSLog(@"COUNT: %d | %i", (int)arr.count, 1 < ((int)arr.count - 1));
See this topic for some ways to deal with this common source of bugs: Constant bugs from [NSArray count] being unsigned
Upvotes: 7
Reputation: 1379
the [arr count]
returns (NSUInteger)
which is nothing but typedef unsigned long NSUInteger;
So there won't be any negative numbers for NSUInteger
. The values start from 0 to some max value and it will be like a loop as follows
... | MAX-2 | MAX-1 | MAX | 0 | 1 | 2 | 3 | 4 | ...
-1 -1 -1 -1 -1 -1 -1
So, the math is like 2-1 = 1
1-1 = 0
0-1 = MAX
0-2 = MAX-1
Upvotes: 2
Reputation: 20993
The count
property of arrays is of NSUInteger
type, which means unsigned long
. The expression arr.count - 1
is subtracting 1 from unsigned integer, so the result is unsigned as well. Instead of -1 you get very large positive number because of overflow, and this number is greater than 1.
Upvotes: 3
Reputation: 726499
The reason why this happens is that 1
on the left is treated as unsigned. In turn, this happens because arr.count
is of unsigned type, making the expression arr.count-1
unsigned as well. When you subtract 1
from an unsigned zero, you get an underflow, and the result is a very large positive number.
To avoid problems like this, be extremely careful with subtraction when dealing with values of unsigned
types. Prefer addition to the other side - specifically, rather than writing
if (a < unsignedB - c)
write
if (a+c < unsignedB)
Upvotes: 4