I have the following code:
int main() {
int n = 3, m = 4, a[n][m], i, j, (* p)[m] = a;
for (i = 0; i < n; i++)
for (j = 0; j < m; j++)
a[i][j] = 1;
p++;
(*p)[2] = 9;
return 0;
}
I have a hard time understanding what p is here, and the consequences of the operations on p in the end. Can someone give me a brief explanation of what happens. I know c-pointers in their simple settings, but here it get sl开发者_如何学Cightly more complicated.
a
is an array of int[m]
, and p
is a pointer to int[m]
. It's initialized to a
, which decays to a pointer to its first element.
Dereferencing p
yields int[m]
, which decays to int*
(pointer to its first element). So (*p)[2]
adds 2
to the int*
that was the result of the decay. So it's setting the third of the first 4
integers (int[m]
, with m
being 4) to 9
.
Adding to p
would advance the address stored in it by units of sizeof(int[m])
bytes, which at runtime (since m
is not a compile time constant) evaluates to 4 * sizeof(int)
. So (*(p+1))[2]
would access the third of the second 4
integers. In total, p
has 3
such arrays of 4
ints to point to: a+0
, a+1
and a+2
.
Notice that you created a C99 VLA, variable length array. You need to #define
n
and m
to integer constants to get rid of those VLAs (which aren't quite portable among C compilers).
p
is a pointer to a 4-element int
arrays (i.e. a pointer to pointer to int
, where the first dimension is 4 and the second is unknown). When you increment p
, it points to the next 4-element int
array, i.e. the fifth int
altogether. Then p
is dereferenced with offset 2, which means that the seventh int
changes, so you get
1 1 1 1
1 1 9 1
1 1 1 1
as the final state of the 4x3 array.
Some small print statements should make clear what this code does:
#include <stdio.h>
int main() {
int n = 3, m = 4, a[n][m], i, j, (* p)[m] = a;
for (i = 0; i < n; i++)
for (j = 0; j < m; j++)
a[i][j] = 1;
printf("p points to %u, sizeof(int)*m = %d", p, sizeof(int)*m);
p++;
printf(", p++ points to %u\n", p);
(*p)[2] = 9;
for (i = 0; i < n; i++)
for (j = 0; j < m; j++)
printf("a[%d][%d] = %d\n", i, j, a[i][j]);
return 0;
}
Example output:
p points to 2293536, sizeof(int)*m = 16, p++ points to 2293552
a[0][0] = 1
a[0][1] = 1
a[0][2] = 1
a[0][3] = 1
a[1][0] = 1
a[1][1] = 1
a[1][2] = 9
a[1][3] = 1
a[2][0] = 1
a[2][1] = 1
a[2][2] = 1
a[2][3] = 1
Clearly, p
is a pointer to int[m]
, so p++
will advance the pointer to the next row in a
. That is why (*p)[2]
will change a[1][2]
. If you didn't increment p
, that line would change a[0][2]
.
Hope that was simple enough!?
精彩评论