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.