cllvmarmv7ipad-2ios6.1

C Pointer to negative length array strange behaviour Apple LLVM compiler


I know that negative length arrays have undefined behaviours, but with the standard of E1[E2] being identical to (*((E1)+(E2))) I expected something to work.

So in this instance what I do is I create an array that spans in direction -32, so the accessible indexes I expected to gain are -31 up to 0.

I am using 8bit unsigned chars of 0 to 255 and signed chars of -128 to +127, but this happens with 32bit integers and 64bit integers too.

I use C99's ability to declare arrays of variable length to construct the negative spanning array, specifically I am compiling to the GNU99 C standards.

I assign these values to the indexes and print them out as I go, all seems to work fine.

It goes strange when I make a pointer to the value at array index [-31] and then loop through that, 0 to 31, printing the values.

const signed char length = 32;
const signed char negativeLength = -length;

signed char array[negativeLength];
for ( signed char ii = 0; ii > negativeLength; ii-- ) {
    array[ii] = ii;
    printf( "array %d\n", array[ii] ); /* Prints out expected values */
}

printf( "==========\n" );

signed char * const pointer = &array[negativeLength + 1];
for ( unsigned char ii = 0; ii < length; ii++ ) {
    printf( "pointer %d\n", pointer[ii] ); /* Begins printing expected values then goes funky */
}

I get different results every time, but with 32 it generally starts out okay for the first 3 values, it then goes funky and starts printing out -93 up to +47 and then at index pointer[8], array[-23] it goes fine again.

I am running this on an iPad 2.

What exactly is going on here? Is the iPad messing with the pointer or the array when it detects the negative spanning array length?


Solution

  • I sometimes advocate understanding the behavior observed in some C implementations in situations where the C standard does not define the behavior, because it can be illuminating about how certain implementing work or how computers work. In this case, however: Do not do that.

    To access an array with arbitrary integer indices, from X (inclusive) to Y (exclusive), do this:

    ElementType ArrayMemory[Y-X], *Array = ArrayMemory - X;
    

    If X <= 0 <= Y and X < Y, the behavior of this is defined by the C standard.