Under most circumstances1, an expression of type "N-element array of T" will be converted ("decay") to expression of type "pointer to T", and the value of the expression will be the address of the first element in the array.
The expression c has type int [1][1]; by the rule above, the expression will decay to type int (*)[1], or "pointer to 1-element array of int", and its value will be the same as &c[0]. If we dereference this pointer (as in the expression *c), we get an expression of type "1-element array of int", which, by the rule above again, decays to an expression of type int *, and its value will be the same as &c[0][0].
The address of the first element of the array is the same as the address of the array itself, so &c == &c[0] == &c[0][0] == c == *c == c[0]. All of those expressions will resolve to the same address, even though they don't have the same types (int (*)[1][1], int (*)[1], int *, int (*)[1], int *, and int *, respectively).
1 - the exceptions to this rule are when the array expression is an operand of the sizeof, _Alignof, or unary & operators, or is a string literal being used to initialize another array in a declaration
*c[0]. You can test this by initilizing to zero and trying the two "dereferences".cin an expression ends up pointing to the first element, and*cdereferences that value**cwill evalute to zero (if you initilize to zero).*cdereferences to another array. So the first element ofcis an array, and by deferencingcyou will return that array, but it too must decay to a pointer to its first element, which is the actualintelement. I was using "value" in a generic sense of whatever that type is, whether it's an array, etc., not "value" as-in the value of theint.