I am confused as to why the sizeof the pointer to a is 20.
The size of a pointer to a is typically not 20.
I thought *a gives you the address of a[0][0]
It does not. The unary * is the indirection operator. When you indirect through a pointer, you get the pointed value. It's the opposite operation of getting an address.
Now, a is not a pointer. It is an array. But an array can implicitly convert to a pointer to the first element. So, a which is an array of 5 arrays of 5 ints implicitly converts to a pointer to an array of 5 ints. When you indirect through that pointer, the result is an lvalue to an array of 5 ints that is the first element of a.
You are printing the size of an array of 5 ints. That happens to be 20 on your system.
Does that mean that a itself stores all the memory for all 5 integers ...
An array stores all of its elements within itself. a stores all the memory of all 5 arrays, and each of the arrays contains the memory of all 5 integers each (25 in total).
but [cout << a;] only prints the address of the first one?
There are no stream insertion operator overloads for arrays. But, there is a stream insertion operator overload for void*, and array can implicitly convert to a pointer to first element which can implicitly convert to void*. So, you are printing the address of the first element of the array.