3

some days ago I've read a post written by another user regarding comparisons between NSNumber objects using the < (less) operator.. He was getting wrong results and people told him that it was comparing the addresses of the NSNumber objects instead of their values... I've tried to reproduce the problem but there is something I'm missing:

int main (int argc, char*argv[])
{
        NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
        NSMutableArray *arrayDistance = [NSMutableArray array];

        [arrayDistance addObject:
                [NSNumber numberWithInteger: 10]];
        [arrayDistance addObject:
                [NSNumber numberWithInteger: 20]];
        [arrayDistance addObject:
                [NSNumber numberWithInteger: 8]];
        [arrayDistance addObject:
                [NSNumber numberWithInteger: 9]];

        int iMinor = 0;
        int i;
        for (i = 0; i < [arrayDistance count]; i++) {
                if([arrayDistance objectAtIndex: i] < [arrayDistance objectAtIndex: iMinor])
                {
                        iMinor = i;
                }
        }

        NSLog(@"iMinor is %d", iMinor);

        [pool release];

        return 0;
}

The code above correctly returns 2, why? Shouldn't it be comparing the addresses instead of the values of the NSNumber objects within the arrayDistance array? Shouldn't it be necessary to get the integer value out of the NSNumber objects or use the compare method of the NSNumber objects?

Does the NSNumber class overload the < (less) operator in order to compare the actual values stored within the objects? If so, where is it written in the reference documentation?

I hope the question is clear. Thank you in advance for any help.

Gianni Costanzi
  • 6,054
  • 11
  • 48
  • 74

1 Answers1

11

The code above correctly returns 2, why? Shouldn't it be comparing the addresses instead of the values of the NSNumber objects within the arrayDistance array? Shouldn't it be necessary to get the integer value out of the NSNumber objects or use the compare method of the NSNumber objects?

It is comparing the addresses of the NSNumber objects, and yes, you should either get the underlying integer value or use -compare:.

What’s happening under the hood is that Lion uses tagged pointers for (a subset of) NSNumber instances that represent integers. Because of the tagged pointer representation, the addresses in your particular example end up having the same order as the underlying integers they represent.

If you print the actual addresses with

printf("%p\n", [arrayDistance objectAtIndex:i]);

you’ll get:

0xac3
0x14c3
0x8c3
0x9c3

Ignoring the least significant byte:

0xa  = 10
0x14 = 20
0x8  = 8
0x9  = 9

As you can see, those addresses do map the underlying integer values.

Note, however, that this is an implementation detail that varies according to the target platform and can change in the future. You shouldn’t depend on it.

Does the NSNumber class overload the < (less) operator in order to compare the actual values stored within the objects? If so, where is it written in the reference documentation?

No, there is no operator overloading in Objective-C.