Change string with pointer
These two codes should change the char 2
in the character'4'
int main(int argc, char *argv[]){
char *s = "hello";
*(s+2)='4';
printf( "%s\n",s);
return 0;
}
When I run this, I get a segmentation error when I run this:
int main(int argc, char *argv[]){
char *s = argv[1];
*(s+2)='4';
printf( "%s\n",s);
return 0;
}
I know there are other ways to do this. What is the difference between the two programs?
source to share
In your first case, you are running into undefined behavior when trying to modify a string literal. Segmentation fault is one of the common side effects of UB.
In your code
char *s = "hello";
essentially puts the starting address of the string literal "hello"
in s
. Now you want to change the content *s
(or *(s+n)
if it's n
not out of scope) it will actually try to change that string literal. As usual, string literals are stored in persistent memory and are usually not allowed to be modified. Quoting from C11
, chapter Β§6.4.5, string literals, (emphasis mine)
It is not specified if these arrays are different if their elements have corresponding values. If the program tries to modify such an array, the behavior is undefined.
However, in the second case, you do
char *s = argv[1];
which puts the value argv[1]
in s
. Now s
points to the line contained in argv[1]
. Here the content argv[1]
(or, argv[n]
which is shared) is not read-only, it can be changed. So using *s
(or *(s+n)
, if n
not out of scope), you can change the content.
This case is determined by the behavior , since according to Β§5.1.2.2.2 starting the program
The parameters
argc
andargv
, and the strings pointed to by the arrayargv
can be modified by the program and retain their last saved values ββbetween the start of the program and the end of the program.
Thus, the second case is a special use case argv[n]
, which is modified according to the standard C rules.
source to share
When you do
char *s = "hello";
you assign *s
to indicate the start of a string literal that is not modifiable . This means that you can read what is there, but you cannot change it (which is why
*(s+2)='4';
gives you segmentation fault.
In your second case, you are not casting your pointer to a string literal so that it can be modified.
In fact, in the second case, you are using argv
which is explained specifically , which can be changed in the c standard.
source to share
literal: "hello" is in read-only memory, so it cannot be changed.
Trying to change it raises a seg failure event
Trying to change the array of strings from argv [] has the same problem. Read-only values
Attempting to change the command line argument raises the seg failure event.
You can use: 'char s [] = "hello"; 'as this will push the literal onto the stack where it can be modified.
You can copy 'strcpy ()' after getting the length of the command line argument and doing malloc () for that length + 1
source to share