This is a really basic question but I did not find a clear answer. I try to understand how string literals in C work.
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char *str = "Hello World!";
str = "Reassign str.";
char *str2 = "Something.";
str = strdup(str2);
free(str);
exit(EXIT_SUCCESS);
}
When I do str = "Reassign str." or str = strdup(str2) to a string literal what happens to the Hello World string? Is it part of the executable, does it go out of scope, is it's memory freed after I reassign str?
String literals have static storage duration. They are not destroyed and have the same addresses during the program execution.
In these statements
str = "Reassign str.";
//...
str = strdup(str2);
pointer str is just reassigned by some other addresses. In the first statement it gets the address of the first character of string literal "Reassign str." and in the second statement it gets the address of the dynamically allocated memory for the character array that contains a copy of the string literal pointed to by str2.
According to the C Standard (6.4.5 String literals)
6 In translation phase 7, a byte or code of value zero is appended to each multibyte character sequence that results from a string literal or literals.78) The multibyte character sequence is then used to initialize an array of static storage duration and length just sufficient to contain the sequence. For character string literals, the array elements have type char, and are initialized with the individual bytes of the multibyte character sequence.
And (6.2.4 Storage durations of objects)
3 An object ...has static storage duration. Its lifetime is the entire execution of the program and its stored value is initialized only once, prior to program startup
As for the string literals themselves then you may not change them. Any attempt to change a string literal results in undefined behaviour of the program.
From the C Standard (6.4.5 String literals)
7 It is unspecified whether these arrays are distinct provided their elements have the appropriate values. If the program attempts to modify such an array, the behavior is undefined.
For example you may not write
char *str = "Hello World!";
*str = 'h';
When you do
char *str = "Hello World!";
compiler sets aside memory of bytes strlen(str) + 1 for that string literal. When the pointer str being reassigned, the memory allocated for string literal "Hello World!" is not destroyed/freed, rather it persist in its scope.
All is Ok in your code.
char *str = "Hello World!";
Ok you declare a char * pointing to a string litteral. To be correct, you should have written const char *str = because a string litteral is an unmodifiable string (str[4] = 'u'; would be incorrect)
str = "Reassign str.";
Ok the pointer str now point to another string litteral. Same remark as above, it should still be const.
char *str2 = "Something.";
Still same story
str = strdup(str2);
Now str points to a malloc'ed string. For the first time it is correct for str not to be const. str[0] = 's'; would be correct here.
free(str);
Fine, you free the string allocated by strdup.
exit(EXIT_SUCCESS);
You nicely return a defined value (0) to the environment.