array subscript are equivalent to pointer arithmerics: a[x] = *(a + x). It is completely legal to subscript with negative numbers. However if variable you applying subscript operator is not pointing to the middle of the array (so resulting pointer would point to the valid element) it will cause undefined behavior.
You got lucky and nothing breaks. If you add more code, recompile your program or moon phase changes, your program can crash, output something unexpected or summon demons from your nose.
Your code works, but it is not legal.
Following is legal BTW:
1 2 3 4
int arr[15];
int* p = arr + 10;
p[-4] = 6;
std::cout << -4[p];
wait, shouldn't "a" have value of 1? as it was created before "x" array, and therefore x-1 was accessing its memory?
The point is that you are accessing out of bounds memory, and the result is that you are corrupting other memory.
If it seems unpredictable or unintuitive, that's because it is. This is a very bad/dangerous thing to do and you can't always predict what will happen.
wait, shouldn't "a" have value of 1? as it was created before "x" array, and therefore x-1 was accessing its memory?
Compiler can place variables in memory how it likes. In fact, if I turn o n optimisation it will output 00, because we do not change these variables (by any legal way) and compiler just throws them out and uses their values directly.
And there is fun thing about UB: compiler can do anything if it encounters undefined behavior. In my case x[-1] got thrown out too and code was simplified to cout << 0 << 0;