Albert Renshaw Albert Renshaw - 5 months ago 6
Objective-C Question

Nested MAX causes smallest value to sometimes be returned when using various object types - MAX(a,MAX(b,c))

I was debugging a while before I found that one of my integers defined as MAX(2,x) was returning -4 even though 2 is clearly larger than -4.

Here is a simplified version of what my code was running so you can experience the irregularity first hand.

NSLog(@"a) %i", (int)MAX(2,-4));
NSString *aString = @"90586381095716439405631195482586763570805293418319186736659080000000000000";
int aNumber = (int)MAX(2,10-MAX(1,(aString.length/5)));
NSLog(@"b) %i", aNumber);
NSLog(@"c) %i", (int)MAX(2,10-MAX(1,16)));


a) will log 2 as expected.

b) will log -4 which makes no sense to me.

c) will log 2 as expected (now b makes even less sense to me)




What am I not getting? MAX is brown in xCode which makes me think it's set as CLANG somewhere in UIKit or Math library, if that's the case perhaps the inner MAX gets processed only after the first MAX has been processed and therefor nesting MAXs will result in weird bugs. But if that were the case wouldn't c) have also logged -4?

Answer

I don't use Objective-C, but the length of the string is probably an unsigned value. If it works the same way as plain C, that would cause the result of the inner MAX to be unsigned as well, and therefore the subtraction from 10 will be performed as unsigned. This will cause the value to underflow and result in a very large value, something like 4294967292 assuming 32 bit ints, and therefore it will be chosen by the outer MAX.

The final int is what then converts it back to signed and you end up with a negative value. If your compiler is any good and you leave the (int) out, you should get a warning about it.

Moral of the story, don't use extraneous casts, that causes the compiler to not give you valuable warnings.

Comments