The first thing to understand is what you type:
cout<<A[0]<<" "<<&A<<" "<<*A;
Expression A[0] an lvalue expression of type int[5] , referring to the first internal array inside A , &A is an rvalue expression of type int (*)[5][5] , which points to array A Finally *A equivalent to A[0] , that is, an lvalue expression of type int[5] .
There are no operators in this language that cannot provide them, which will unload either int[5] or int (*)[5][5] , so the compiler tries to find the best match and finds that there is an operator that prints a void* . int[5] can decay to int* , which refers to A[0][0] , and is itself converted to void* . int (*)[5][5] is a pointer and, therefore, is converted to void* , so overload is acceptable for both cases.
The language defines the layout of the array in memory and, in particular, requires that the array and the first element of the array are located in the same memory address, so if you had to print the addresses &A and &A[0] it would print the same value, and since &A[0] also in the same memory location of the first of its elements, &A[0][0] also refers to the same address.
Returning to the code above, you type:
cout<< static_cast<void*>(&A[0][0]) << " " << static_cast<void*>(&A) << " " << static_cast<void*>(&A[0][0]);
which, following the reasoning above, must have the same exact value, even if the type in the second case does not match.
David Rodríguez - dribeas
source share