How does pointer arithmetic - specifically, addition with numbers - work if the pointer points to a multidimensional array?
When I debugged the sample program below:
int main(void) {
int a[3][4] = {{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12}};
int *p1 = a;
// set breakpoint ...
...
}
If I use debugger (CLion) to print *(p1 N)
, it gives me an array having (N 1)
elements, starting from element a[N / col_size][N % col_size]
. This doesn't match my expectation. Listing actual result and expectation as below:
Enter into debugger to print | Debugger result | Expectation |
---|---|---|
*(p1) |
{1} |
{1, 2, 3, 4} |
*(p1 2) |
{3, 4, 5} |
{9, 10, 11, 12} |
*(p1 5) |
{6, 7, 8, 9, 10, 11} |
{an array of random numbers} |
*(p1 6) |
{7, 8, 9, 10, 11, 12, -11} . -11 is random as it already exceeded the allocated size of the array. |
{an array of random numbers} |
I understand that C stores multidimensional array in row-major order, but what confuses me is why does C provide an array of (N 1) length for *(p1 N)?
CodePudding user response:
This is wrong:
int *p1 = a;
a
degenerates into a pointer to its first element. It's first element is an int[4]
so a
degenerates into an int (*)[4]
. gcc says as much:
warning: initialization of 'int *' from incompatible pointer type 'int (*)[4]'
You're assigning it to an int *
, which strict aliasing violation and therefore undefined behaviour.
If you had used the correct type, the output you would received would have been more in line with your expectations.
CodePudding user response:
Your array could be looked at as the following
a 0 1 2 3
0 {1, 2, 3, 4},
1 {5, 6, 7, 8},
2 {9, 10, 11, 12}
However, it is allocated in memory linearly like the following. a
is always associated with element [0][0]. Therefore after int *p1 = a;
p1 will point to the same element.
0 1 2
======= ======= ==========
1 2 3 4 5 6 7 8 9 10 11 12
a---^
p1 -^
Pointer arithmetic with int *
types will increment/decrement the pointer so that it would point to the next/previous int
element. If the int is 8 bytes, than the pointer will be incremented/decremented by the multiple of 8.
As a result the following represent the arithmentic.
======= ======= ==========
1 2 3 4 5 6 7 8 9 10 11 12
p1 2 -----^ ^
p1 5 -----------
And as a result, *p = 1
, *(p 2) = 3
, *(p 5) = 6