Reputation: 339
Observe the following code:
const char *str1 = "foo";
printf("1.1: %s\n", str1);
str1 = "bar";
printf("1.2: %s\n\n", str1);
const char *str2[] = { "foo", "bar" };
printf("2.1: %s\n", str2[0]);
str2[0] = "baz";
printf("2.2: %s\n\n", str2[0]);
char *str3 = malloc(4);
strcpy(str3, "foo");
const char *str4[] = { str3, "bar" };
printf("3.1: %s -- %s\n", str4[0], str4[1]);
//str4[0][0] = 'z';
str4[0] = "bar";
str4[1] = "baz";
printf("3.2: %s -- %s\n", str4[0], str4[1]);
free(str3);
Wrapping it in a standard main
function and compiling with gcc -Wall -Wextra -o test test.c
, this gives no warnings and the output is:
1.1: foo
1.2: bar
2.1: foo
2.2: baz
3.1: foo -- bar
3.2: bar -- baz
When uncommenting the only commented line, gcc complains error: assignment of read-only location ‘*str4[0]’
. Of course this is expected, I only added that bit for completeness.
By my understanding all the other assignments are valid because I'm not modifying the already existing read-only memory, I'm replacing it in its entirety with another memory block (which is then also marked read-only). But is this legal throughout all C compilers, or is it still implementation-dependent and therefore can it result in undefined behaviour? It's a little hard to find good information on this because it always seems to be about modifying the existing memory through pointer magic or casting the const
away.
Upvotes: 3
Views: 89
Reputation: 310970
In this declaration
const char *str1 = "foo";
the pointer (variable) str1
is not constant. It is the string literal pointed to by the pointer str1
that is constant. That is the (non-constant) pointer str1
points to a constant object of the type const char
.
So you may not change the literal pointed to by the pointer like for example
str1[0] = 'g';
But you may change the variable str1
itself because it is not constant
str1 = "bar";
To declare the pointer str1
as a constant pointer you should write
const char * const str1 = "foo";
In this case you may not write
str1 = "bar";
Because now the pointer str1
itself is constant.
Pay attention to though in C string literals have types of non-constant character arrays nevertheless you may not change a string literal. Any attempt to change a string literal results in undefined behavior.
That is you may not write
char *str1 = "foo";
str1[0] = 'g';
Upvotes: 3