Question

I am not sure if this only happens on Apple's LLVM Compiler 4.0 (XCode 4.4.1), but I noticed the following behaviour:

NSUInteger currentIndex = 0;
NSUInteger sideSize = 2;

// Method A
for (NSInteger i = currentIndex-sideSize; i < currentIndex+sideSize; i++)
{
    printf("In the loop\n"); // WON'T be executed
}

// Method B
for (NSInteger i = (NSInteger)(currentIndex-sideSize); i < currentIndex+sideSize; i++)
{
    printf("In the loop\n"); // WON'T be executed
}

// Method C
for (NSInteger i = (NSInteger)(currentIndex-sideSize); i < (NSInteger)(currentIndex+sideSize); i++)
{
    printf("In the loop\n"); // WILL be executed
}

// Method D
NSInteger initialIndex = currentIndex-sideSize;
NSInteger finalIndex = currentIndex+sideSize;
for (NSInteger i = initialIndex; i < finalIndex; i++)
{
    printf("In the loop\n"); // WILL be executed
}

Method B and Method C are almost the same except we are not explicitly casting the result of the addition operator to a signed value.

Can anyone please explain what is happening?

Was it helpful?

Solution

The thing is that if in an expression there are signed and unsigned operands, as per the C standard, the signed operand will be promoted to unsigned integer. What happens then is if you subtract 2 from 0, that results in -2, but since it's treated as an unsigned integer (when comparing the values), it's overflowing and ends up being some large number. That's why the loop in Method B doesn't execute and the loop in Method C does (when you explicitly cast the result and/or the operands to signed, the overflow doesn't occur and the loop correctly goes from -2 to 2).

That's a weird thing in the C standard, not in LLVM. LLVM perfectly follows the standard here.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top