I have a simple program:
int main() {
    char *c = "message";
    char *z = "message";
    if ( c == z )
        printf("Equal!\n");
    else
        printf("Not equal!\n");
    return 0;
}
I wanted to know why this prints Equal!, even when compiled with optimisations turned off (-O0). This would indicate that both c and z point to the same area of memory, and thus the first mutation of z (for example, changing z[0] to a) will be expensive (requiring a copy-and-write). 
My understanding of what's happening is that I'm not declaring an array of type char, but rather am creating a pointer to the first character of a string literal. Thus, c and z are both stored in the data segment, not on the stack (and because they're both pointing to the same string literal, c == z is true). 
This is different to writing:
char c[] = "message";
char z[] = "message";
if ( c == z ) printf("Equal\n");
else printf("Not equal!\n");
which prints Not equal!, because c and z are both stored in mutable sections of memory (ie, the stack), and are separately stored so that a mutation of one doesn't effect the other. 
My question is, is the behaviour I'm seeing (c == z as true) defined behaviour? It seems surprising that the char *c is stored in the data-segment, despite not being declared as const. 
Is the behaviour when I try to mutate char *z defined? Why, if char *c = "message" is put in the data segment and is thus read-only, do I get bus error rather than a compiler error?  For example, if I do this:
char *c = "message";
c[0] = 'a';
I get:
zsh: bus error  ./a.out
although it compiles happily.
Any further clarification of what's happening here and why would be appreciated.
 
     
     
     
    