The difference here is that
char *s = "Hello world";
"Hello world" in the read-only parts of the memory, and making
s a pointer to that makes any writing operation on this memory illegal.
char s = "Hello world";
puts the literal string in read-only memory and copies the string to newly allocated memory on the stack. Thus making
s = 'J';