c++integer-overflow

Unsigned underflow doesn't happen in subscript operator, why?


I have always thought the next example is undefined behaviour (accessing array out of bounds):

int main()
{
    int* a= new int[3];
    a[0] = 100;
    a++;
    
    unsigned long index = 0;
    
    printf("%d\n", a[-1]);
    printf("%d\n", a[index - 1]);
    printf("%ul\n", index - 1);
}

However, this outputs just fine:

100
100
4294967295l

Why doesn't underflow happen in subscript operator?


Solution

  • Why doesn't underflow happen in subscript operator?

    printf("%d\n", a[-1]); has defined behaviour. Pointer arithmetic works with any integral type, so the signed int value -1 is added to a, resulting in an in-bounds access, to an element that was initialised.

    printf("%d\n", a[index - 1]); has undefined behaviour. index - 1 is a mixed-rank integral expression, and unsigned long has a greater1 rank than int, so it is an unsigned expression, equivalent to std::numeric_limits<unsigned long>::max(). Adding this to a is out of bounds, thus undefined behaviour. Because the standard places no requirements on the observed behaviour, printing 100 is conformant.

    printf("%ul\n", index - 1); has undefined behaviour. lu is the correct format specifier for unsigned long.

    1. Equal ranks also result in conversion to unsigned, so it would need to be unsigned short to have defined behaviour.