Search code examples
cpointersscopedynamic-memory-allocation

Why is the output of the code 8,5,5 and not 8,8,5?


#include<stdio.h>
#include<stdlib.h>

void f(int x, int* y, int **z)
{
    *z = malloc(sizeof(int));
    **z = 4;
    **z += 1;
    x += 2;
    *y += 3;
}

int main()
{
    int x = 5;
    int *y = &x;
    int **z = &y;
    f(x, y, z);
    printf("%d, %d, %d", x, *y, **z);
    return 0;
}

So,here is my take on the problem-

first in the main z and y point to x which is 5.When function is called new variables x,y,z are created of their types and y,z in the function beginning eventually point to the x in the main.Now z is made to point to a int space in heap.Here the value of z pointing to the heap becomes 5.then x in the function becomes 7 and in the last line of function *y+=3 makes an increment to x value in main (making it 8).

now the flow of control returns to main

and x should be x in main that is 8 y should be 8 since it points to x in main. and z should be 5 since it points in the heap.

where did I go wrong?


Solution

  • f's z points to main's y, not f's y. main's y and f's y are distinct variables, even if they have the same value for a time. Changing one doesn't change the other.


    I'm going to illustrate what is happening as we step through the program line by line (more or less). But first, I'm going to rename f's parameters to avoid confusion.

    void f(int a, int* b, int **c)
    {
        *c = malloc(sizeof(int));
        **c = 4;
        **c += 1;
        a += 2;
        *b += 3;
    }
    
    1. After

      int x = 5;
      int *y = &x;
      int **z = &y;
      

      we have

      int **z @ 3000     int *y @ 2000      int x @ 1000
      +-----------+      +-----------+      +-----------+
      | 2000   --------->| 1000   --------->|         5 |
      +-----------+      +-----------+      +-----------+
      

      (All addresses invented. The exact numbers are irrelevant.)

    2. We call f. This copies main's x, y and z into f's a, b and c.

      int **z @ 3000     int *y @ 2000      int x @ 1000
      +-----------+      +-----------+      +-----------+
      | 2000   ------+-->| 1000   ------+-->|         5 |
      +-----------+  |   +-----------+  |   +-----------+
           ||        |        ||        |        ||
           ||        |        ||        |        ||
          copy       |       copy       |       copy
           ||        |        ||        |        ||
           VV        |        VV        |        VV
      int **c @ 6000 |   int *b @ 5000  |   int a @ 4000
      +-----------+  |   +-----------+  |   +-----------+
      | 2000   ------+   | 1000   ------+   |         5 |
      +-----------+      +-----------+      +-----------+
      
    3. After

      *c = malloc(sizeof(int));
      

      we have

                                            int @ 7000
                                            +-----------+
                                       +--->| ????????? |
                                       |    +-----------+
                                       |
      int **z @ 3000     int *y @ 2000 |    int x @ 1000
      +-----------+      +-----------+ |    +-----------+
      | 2000   ------+-->| 7000   -----+ +->|         5 |
      +-----------+  |   +-----------+   |  +-----------+
                     |                   |
      int **c @ 6000 |   int *b @ 5000   |  int a @ 4000
      +-----------+  |   +-----------+   |  +-----------+
      | 2000   ------+   | 1000   -------+  |         5 |
      +-----------+      +-----------+      +-----------+
      

      Remember that c points to main's y.

    4. After

      **c = 4;
      **c += 1;
      a += 2;
      *b += 3;
      

      we have

                                            int @ 7000
                                            +-----------+
                                       +--->|         5 | (4+1)
                                       |    +-----------+
                                       |
      int **z @ 3000     int *y @ 2000 |    int x @ 1000
      +-----------+      +-----------+ |    +-----------+
      | 2000   ------+-->| 7000   -----+ +->|         8 | (5+3)
      +-----------+  |   +-----------+   |  +-----------+
                     |                   |
      int **c @ 6000 |   int *b @ 5000   |  int a @ 4000
      +-----------+  |   +-----------+   |  +-----------+
      | 2000   ------+   | 1000   -------+  |         7 | (5+2)
      +-----------+      +-----------+      +-----------+
      
    5. Then, back in main, we print x, *y (the anon block), and **z (again, the anon block via *y).