Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Basic C pointer and pass by reference confusion

Tags:

c

I have following basic program:

#include <stdio.h>

void doit(char *c) {
    c = "world";
}

int main() {
    char *c = "hello";
    doit(c);
    printf("%s\n", c);
    return 0;
}

Going line by line:

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

Now when c (pointer) is passed to the function which tries to modify it. The modified value is not available within 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 just fine? I am expecting first example to work fine by itself since I am passing doit(c) which is already a pointer to string I want to modify.

like image 292
Stupid Avatar asked Dec 15 '14 11:12

Stupid


2 Answers

It's because in the first version you pass the pointer by value. That means the actual pointer from main is copied and in the doit function you only modify the copy.

In the second version you emulate pass by reference (C doesn't have proper references) by passing a pointer to the pointer.


Lets see if this makes it clearer for you.

For the first program, in the main function you have a pointer c that 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 you change the pointer in doit you have this:

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

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

For the second program it start out the same:

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

But then it changes when you call using a pointer to the pointer:

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

Then dereferencing c in doit gives you the original c pointer from main, and changing it you have

+--------+       +--------+       +---------+
| doit:c | ----> | main:c | ----> | "world" |
+--------+       +--------+       +---------+
like image 63
Some programmer dude Avatar answered Sep 21 '22 07:09

Some programmer dude


In first case:-

void doit(char *c)

you are passing pointer by value. And as we know that passing something by value to function means that function can't change original value passed.

like image 20
ravi Avatar answered Sep 19 '22 07:09

ravi