The fact that "the array name is the address of the zeroth element" is true most of the time1 does not mean that you can assign it anything. Although this
char str[] = "hello";
looks like an assignment, it is in fact initialization; the concept of lvalue does not apply to it.
Moreover, obtaining an address using &
operator never produces an lvalue, so there is no way to come up with an X
that does not break your first three examples.
The last two, however, can be assigned, with some minor tweaks:
*c_arry = 'x'; // the same as c_arry[0] = 'x'
char *c_arry_of_ptr[2];
...
*c_arry_of_ptr[0] = 'x';
1 One notable exception is
sizeof(c_arry)
- here, it's not the same as sizeof(&c_arry[0])
for arrays of size other than 1
.