Search code examples
arrayscpointersmemory-address

Array subscripting and pointer arithmetics in C give different result


I am getting different memory address (invalid one) when trying to obtain the address of the value located inside of an array when using array subscript syntax as opposed to when using pointer arithmetic which indeed yields expected (correct) memory address. Why is that?

This code was compiled with gcc C99 and C11, flags: -Wall -O0.

#include <stdio.h>

int main() {
    unsigned int arg = 0;
    char         arr[5] = {'a', 'b', 'c', 'd', 'e'};
    char*        arrp   = arr + 2;
    char*        pos_1  = arrp - arg - 1;
    char*        pos_2  = &arrp[-arg - 1];
    printf("arr:  %p\narrp: %p\npos_1:%p\npos_2:%p\n", arr, arrp, pos_1, pos_2);
    return 0;
}

Results in:

arr:  0x7fff31035a73
arrp: 0x7fff31035a75
pos_1:0x7fff31035a74
pos_2:0x800031035a74

pos_2 is invalid as you can see.

But when using a constant 0 as opposed to a variable arg I get the correct memory address for pos_2 also...

#include <stdio.h>

int main() {
    char         arr[5] = {'a', 'b', 'c', 'd', 'e'};
    char*        arrp   = arr + 2;
    char*        pos_1  = arrp - 0 - 1;
    char*        pos_2  = &arrp[-0 - 1];
    printf("arr:  %p\narrp: %p\npos_1:%p\npos_2:%p\n", arr, arrp, pos_1, pos_2);
    return 0;
}

This results in:

arr:  0x7ffc270c4ed3
arrp: 0x7ffc270c4ed5
pos_1:0x7ffc270c4ed4
pos_2:0x7ffc270c4ed4

which is correct (compiled second time).


Solution

  • Since arg is unsigned, -arg - 1 makes an unsigned with the value UINT_MAX (0u - 1 "wrapps around" and becomes the largest possible unsigned) - which is out of bounds of pretty much any array.

    -0 - 1 is on the other hand done using ints and the result is -1.