Except when it is the operand of the sizeof or unary & operators, or is a string literal used to initialize a character array in a declaration, an expression of type "N-element array of T" will be converted ("decay") to an expression of type "pointer to T", and the value of the expression will be the address of the first element of the array.
The expression a has type "3-element array of 5-element array of int"; thus, sizeof a should yield 3 * 5 * sizeof (int).
The expression *a is the same as the expression a[0] (a[i] is defined as *(a + i) - *a is the same as *(a + 0), which is the same as a[0]). Both *a and a[0] have type "5-element array of int"; thus sizeof *a and sizeof a[0] should both yield 5 * sizeof (int).
However...
If you pass a to a function, such as
foo( a );
then a is not the operand of the sizeof or unary & operators, and the expression will be converted from type "3-element array of 5-element array of int" to "pointer to 5-element array of int":
void foo( int (*a)[5] ) { ... }
If you computed sizeof a in function foo, you would not get 5 * sizeof (int), you would get sizeof (int (*)[5]), which, depending on the platform, would be 4 to 8 bytes.
Similarly, if you passed *a or a[i] to a function, what the function actually receives is a pointer to int, not an array of int, and sizeof will reflect that.