"pCow goes MOO"
is a string literal and have two different uses. Either you can use it as an initializer to an array:
char aCow[] = "pCow goes MOO";
In which case the contents of the string literal are copied into the array.
Or alternatively, you can use a string literal as a stand-alone constant array anywhere in your program. For example strcpy(cow, "pCow goes MOO");
. So there's a distinctive difference between these two:
char aCow[] = "pCow goes MOO";
char* pCow = "pCow goes MOO";
In the first case, the literal is copied into the array. In the second case, the literal remains a stand-alone constant in read-only memory, which we point to with a pointer. The former can be modified, the latter cannot.
As for the case of
char *pCow = {'p','C','o','w',' ','g','o','e','s',' ','M','O','O','\0'};
You are using a pointer, but you have no string literal. Instead you have an initializer list intended for an array. A good compiler would warn you for "excess initializer". The reason that the code compiles is a very odd rule in C which is allowing plain variables to be initialized with braces, for example int x = {1};
. So the compiler uses this rule to initialize your pointer to point at the address 'p'
, which is of course nonsense, and then it discards the rest of the initializer list.