Schrodingrrr
Schrodingrrr

Reputation: 4271

1 < -1 evaluates to TRUE

In part of my code I was writing a simple for loop to iterate over elements in an array (all NSMutableDictionarys), 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

Answers (4)

Kristopher Johnson
Kristopher Johnson

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

bhargavg
bhargavg

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

Wojtek Surowka
Wojtek Surowka

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

Sergey Kalinichenko
Sergey Kalinichenko

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

Related Questions