If I have learnt what has been told here well 'array' decays to a pointer, its value is the address of a[0][0] and it refers to the addresses of a[0][0], a[0][1] and a[0][2]
No the name of the array decays to the address of the first element not some other random element.
Is this an exception to the usual way of "both the argument and the formal parameter must be the same type"
No it is not an exception, the function prototype, function implementation, and function call must agree as to the type. Let's simplify things and just talk about one dimensional array for now. Do you realize that when talking about function parameters that the following are all equivalent?
Code:
void someFunction(int *array);
void someFunction(int array[]);
void someFunction(int array[3]); // The number in the brackets is actually ignored by the compiler (remember this is a single dimensional array).
Do you realize that the following are also equivalent?
Code:
int main()
{
...
someFunction(array);
someFunction(&array[0]);
...
Multidimensional arrays just add the brackets with the sizes of all but the last dimension (array[][2], *array[2], or array[3][2]). All dimensions except the first must have the corresponding sizes.