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?

+3


source to share


4 answers


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

and argv

, and the strings pointed to by the array argv

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.

+7


source


As Surav said, trying to modify a string literal causes undefined behavior. If you did the following one at a time, it would work well.



int main(int argc, char *argv[]){   
   char s[] = "hello";   
   *(s+2)='4';
   printf( "%s\n",s);
   return 0;     
}

      

+5


source


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.

+4


source


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

0


source







All Articles