Okay, let's review first, how arrays decay and second, how declarations work.
A
is declared as a 2D array. When A
is used in any expression, it will "decay" to a pointer to its first element. In C, a 2D array is made up of two 1D arrays. So an element of a 2D array is a 1D array. So when A
is used in any expression, it will decay to a pointer to the first row of A
, which is an array of 10 ints.
int (*v) [10]
means that v
is a pointer to an array of 10 ints. The assignment
int (*v)[10] = A;
is an expression, so A
there has decayed to a pointer to 10 ints as well, so the assignment is valid.
So now when you look at **v
, you are dereferencing first, v
, which means you are getting what v
points at, which is the first row of your 2D array. Then you are dereferencing *v
, which means you are getting the first element of that first row. That is 1, so your output is 1.
When you look at **(v + 1)
, you are first adding 1 to the pointer v
. Since v
points to a row, adding 1 gets you a pointer to the next row. Then you do the double dereferencing as above and you get the first element of the next row, which is 11.
When you look at *(*v + 1)
, you are first dereferencing v
, which means you get the first row. Then you add 1 to that, which gets you a pointer to the next element of the row. Then you dereference that, which gets you the 2, the second element.
To summarize: v
points to the whole first row. *v
points to the first element of the first row. (v + 1)
points to the whole second row. (*v + 1)
points to the second element of the first row.
After this, figuring out the rest is probably quite easy.