C base pointer and messy transfer

I have the following main program:

#include <stdio.h> void doit(char *c) { c = "world"; } int main() { char *c = "hello"; doit(c); printf("%s\n", c); return 0; } 

Line wrap:

  • c stores the address of the string (char sequence), it points to
  • * c indicates hello within the main function

Now that c (pointer) is passed to the function that is trying to modify it. The modified value is not available in main. Why?

 #include <stdio.h> void doit(char **c) { *c = "world"; } int main() { char *c = "hello"; doit(&c); printf("%s\n", c); return 0; } 

works great? I expect the first example to work just fine on its own, as I pass doit(c) , which is already a pointer to the line I want to change.

+6
source share
3 answers

This is because in the first version you pass a pointer by value. This means that the actual pointer from main copied, and in doit you are editing only the copy.

In the second version, you emulate pass by reference (C has no corresponding links) by passing a pointer to a pointer.


Let's see if this becomes more clear to you.

For the first program in the main function, you have a pointer c , which points to the string literal "hello" :

  + -------- + + --------- +
 |  main: c |  ----> |  "hello" |
 + -------- + + --------- +

Then, when you pass it to the function, the pointer is copied, so you have this:

  + -------- +
 |  main: c |  -
 + -------- + \ + --------- +
               > -> |  "hello" |
 + -------- + / + --------- +
 |  doit: c |  -
 + -------- +

After changing the pointer in doit , you have the following:

  + -------- + + --------- +
 |  main: c |  ----> |  "hello" |
 + -------- + + --------- +

 + -------- + + --------- +
 |  doit: c |  ----> |  "world" |
 + -------- + + --------- +

For the second program, it starts with the same:

  + -------- + + --------- +
 |  main: c |  ----> |  "hello" |
 + -------- + + --------- +

But then it changes when you call with a pointer to a pointer:

  + -------- + + -------- + + --------- +
 |  doit: c |  ----> |  main: c |  ----> |  "hello" |
 + -------- + + -------- + + --------- +

Then dereferencing c in doit gives the original pointer c from main , and when you change it, you

  + -------- + + -------- + + --------- +
 |  doit: c |  ----> |  main: c |  ----> |  "world" |
 + -------- + + -------- + + --------- +
+8
source

In the first case: -

 void doit(char *c) 

you pass a pointer by value. And since we know that passing something by value to a function means that the function cannot change the original passed value.

+2
source

In the first case, you pass a copy of the c pointer to doit . As a result, any modifications you make to the pointer, they will not be displayed in the caller. You change the place where copy c indicated, but the original c remains unchanged.

Unlike the second example, you pass to the pointer pointer, and when you change the value that it points to, you change the original pointer c .

+1
source

Source: https://habr.com/ru/post/979618/


All Articles