> The identifier "a" can be looked at as a pointer-to-pointer-to-int (int **a)
Erm, no it isn't, and no it can't.
> int a[2][3] = { { 1, 2, 3}, {3, 6, 9 } };
When you say 'a', you get a pointer to the first element of a (the type being int (*)[3])
This is NOT the same as int**
http://www.eskimo.com/~scs/C-faq/q6.3.html
So when you do (a+i), you're really getting a pointer to a[i] (with the aforementioned type). In memory terms, you now have a pointer to the start of an array containing say 3,6,9 (when i=1).
Now when you do *(a+1), this is when you get an int* pointer.
(*(a+1)+j), you have a pointer to a specific element of 3,6,9 (say a pointer to a memory location containing 9, when j=2 say).
*(*(a+1)+j) dereferences that pointer to an int to get the actual integer (9 say).
Code:
#include <stdio.h>
int main ( void ) {
int a[2][3] = { { 1, 2, 3}, {3, 6, 9 } };
int i, j;
for( i = 0; i < 2; ++i )
for( j = 0; j < 3; ++j ) {
int (*p1)[3] = a;
int *p2;
int val;
p1 += i;
p2 = *p1 + j;
val = *p2;
printf("%p %p %d\n",(void*)p1,(void*)p2,val);
}
return 0;
}
Simply mushing p1 to be an int** for example will get you
Code:
$ gcc -Wall bar.c
bar.c: In function `main':
bar.c:8: warning: initialization from incompatible pointer type
$ ./a.exe
Segmentation fault (core dumped)