Sahbi
Sahbi

Reputation: 339

Replacing (not modifying) 'const' values, legal?

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

Answers (1)

Vlad from Moscow
Vlad from Moscow

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

Related Questions