The following code receives seg fault on line 2:
char *str = "string";
str[0] = 'z'; // could be also written as *str = 'z'
printf("%s\n", str);
While this works perfectly well:
char str[] = "string";
str[0] = 'z';
printf("%s\n", str);
Tested with MSVC and GCC.
Normally, string literals are stored in read-only memory when the program is run. This is to prevent you from accidentally changing a string constant. In your first example,
"string"
is stored in read-only memory and*str
points to the first character. The segfault happens when you try to change the first character to'z'
.In the second example, the string
"string"
is copied by the compiler from its read-only home to thestr[]
array. Then changing the first character is permitted. You can check this by printing the address of each:Also, printing the size of
str
in the second example will show you that the compiler has allocated 7 bytes for it:The above sets
str
to point to the literal value"string"
which is hard-coded in the program's binary image, which is probably flagged as read-only in memory.So
str[0]=
is attempting to write to the read-only code of the application. I would guess this is probably compiler dependent though.In the first place,
str
is a pointer that points at"string"
. The compiler is allowed to put string literals in places in memory that you cannot write to, but can only read. (This really should have triggered a warning, since you're assigning aconst char *
to achar *
. Did you have warnings disabled, or did you just ignore them?)In the second place, you're creating an array, which is memory that you've got full access to, and initializing it with
"string"
. You're creating achar[7]
(six for the letters, one for the terminating '\0'), and you do whatever you like with it.String literals like "string" are probably allocated in your executable's address space as read-only data (give or take your compiler). When you go to touch it, it freaks out that you're in its bathing suit area and lets you know with a seg fault.
In your first example, you're getting a pointer to that const data. In your second example, you're initializing an array of 7 characters with a copy of the const data.
Most of these answers are correct, but just to add a little more clarity...
The "read only memory" that people are referring to is the text segment in ASM terms. It's the same place in memory where the instructions are loaded. This is read-only for obvious reasons like security. When you create a char* initialized to a string, the string data is compiled into the text segment and the program initializes the pointer to point into the text segment. So if you try to change it, kaboom. Segfault.
When written as an array, the compiler places the initialized string data in the data segment instead, which is the same place that your global variables and such live. This memory is mutable, since there are no instructions in the data segment. This time when the compiler initializes the character array (which is still just a char*) it's pointing into the data segment rather than the text segment, which you can safely alter at run-time.
The C FAQ that @matli linked to mentions it, but no one else here has yet, so for clarification: if a string literal (double-quoted string in your source) is used anywhere other than to initialize a character array (ie: @Mark's second example, which works correctly), that string is stored by the compiler in a special static string table, which is akin to creating a global static variable (read-only, of course) that is essentially anonymous (has no variable "name"). The read-only part is the important part, and is why the @Mark's first code example segfaults.