When we write
char *s ="hello";
Creates two objects:
- a read-only array of 6
chars containing the values
'h', 'e', 'l', 'l', 'o', '\0', which has no name and has static storage duration (meaning that it lives for the entire life of the program); and
- a variable of type pointer-to-char, called
s, which is initialized with the location of the first character in that unnamed, read-only array.
The "read-only memory" is the text segment in the program. The same place in memory where the instructions are loaded. 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 and our text segment is of type read-only for obvious reasons like security.
So, when we try to change it, a Segmentation fault occurs.
char s = "hello";
Creates one object - a
char array of size 6, called
s, initialized with the values
'h', 'e', 'l', 'l', 'o', '\0'. Where this array is allocated in memory depends on where the declaration appears. If the declaration is within a function, it is allocated on the stack; if it's outside a function, it will probably be stored within an "initialized data segment" which we can safely alter at run time.
Now, in this case character array s1 is created inside the stack section of the memory and p is a pointer to a character. In the second line p is storing the address of the third element of the array.
Notice that p is not pointing to the text segment of the program which is read-only and alteration would give segmentation fault, here p is pointing to the stack section so we can safely alter the values that's why when we do *p = '0' ; it is valid.