As everybody already answered, this:
Is an array of 3 pointers to int. And this:
Is a pointer to an array of 3 ints.
This:
Is a pointer to a pointer which points to an int.
The three declarations are completely different from each other.
In the context of a function, main(), for exemple, the argument argv can be writen as one of these two:
Code:
int main( int argc, char *argv[] )
int main( int argc, char **argv )
They are equivalent because any array in the argument declaration is passed as a pointer. So, if you have something like this:
Code:
// array of 3 ints.
int v[3] = { 0, 1, 2 };
// array of 3 pointers to ints.
int *a[3] = { &v[0], &v[1], &v[2] };
// Prototype. accepts a pointer to a pointer to int.
int f( int **pp );
// Calls f() with a pointer which points to pointers to ints.
f( a );
Here a is converted to a pointer to the first element of the array (identified by the symbol a). Which is the same as:
In the context of memset(), for example, the pointer in the argument points to a buffer which will be filled. A pointer of type int ** will be a pointer which points to an array of pointers, so the pointers pointed will be filled. Let's say:
Code:
memset( ( void * )a, 0, sizeof a );
This will fill the array a with zeroes, so a[0] = a[1] = a[2] = 0 (which is the same as NULL). Notice the array v remains untouched.