代码的输出为8,5,5而不是8,8,5的原因是什么?

huangapple go评论83阅读模式
英文:

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 = (int*)malloc(sizeof(int)); // 改成 (int*)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;
}

主要的修正包括:

  1. malloc 函数的返回值前添加了 (int*) 强制类型转换,以确保它与 int** 类型的指针匹配。
  2. int *y = &x;int **z = &y; 中,去掉了 &amp;,因为这是在初始化指针时不需要的。

这样修改后,你的代码应该能够按照你的预期工作,输出为 "8, 8, 5",表示 x*y**z 的值分别为 8、8 和 5。

英文:
#include&lt;stdio.h&gt;
#include&lt;stdlib.h&gt;

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 = &amp;x;
    int **z = &amp;y;
    f(x, y, z);
    printf(&quot;%d, %d, %d&quot;, 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?

答案1

得分: 4

fz指向mainy,而不是fymainyfy是不同的变量,即使它们在某个时刻具有相同的值。改变一个不会影响另一个。

我将逐行解释程序的执行过程(或多或少)。但首先,我将重命名f的参数以避免混淆。

void f(int a, int* b, int **c)
{
    *c = malloc(sizeof(int));
    **c = 4;
    **c += 1;
    a += 2;
    *b += 3;
}
  1. int x = 5;
    int *y = &amp;x;
    int **z = &amp;y;
    

    之后,我们有

    int **z @ 3000     int *y @ 2000      int x @ 1000
    +-----------+      +-----------+      +-----------+
    | 2000   ---------&gt;| 1000   ---------&gt;|         5 |
    +-----------+      +-----------+      +-----------+
    

    (所有地址都是虚构的。确切的数字无关紧要。)

  2. 我们调用f。这将mainxyz复制到fabc中。

    int **z @ 3000     int *y @ 2000      int x @ 1000
    +-----------+      +-----------+      +-----------+
    | 2000   ------+--&gt;| 1000   ------+--&gt;|         5 |
    +-----------+  |   +-----------+  |   +-----------+
         ||        |        ||        |        ||
         ||        |        ||        |        ||
        复制       |       复制       |       复制
         ||        |        ||        |        ||
         VV        |        VV        |        VV
    int **c @ 6000 |   int *b @ 5000  |   int a @ 4000
    +-----------+  |   +-----------+  |   +-----------+
    | 2000   ------+   | 1000   ------+   |         5 |
    +-----------+      +-----------+      +-----------+
    
  3. *c = malloc(sizeof(int));
    

    之后,我们有

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

    请记住,c指向mainy

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

    之后,我们有

                                          int @ 7000
                                          +-----------+
                                     +---&gt;|         5 | (4+1)
                                     |    +-----------+
                                     |
    int **z @ 3000     int *y @ 2000 |    int x @ 1000
    +-----------+      +-----------+ |    +-----------+
    | 2000   ------+--&gt;| 7000   -----+ +-&gt;|         8 | (5+3)
    +-----------+  |   +-----------+   |  +-----------+
                   |                   |
    int **c @ 6000 |   int *b @ 5000   |  int a @ 4000
    +-----------+  |   +-----------+   |  +-----------+
    | 2000   ------+   | 1000   -------+  |         7 | (5+2)
    +-----------+      +-----------+      +-----------+
    
  5. 然后,在main中,我们打印x*y(匿名块)和**z(再次通过*y的匿名块)。

英文:

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 = &amp;x;
    int **z = &amp;y;
    

    we have

    int **z @ 3000     int *y @ 2000      int x @ 1000
    +-----------+      +-----------+      +-----------+
    | 2000   ---------&gt;| 1000   ---------&gt;|         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   ------+--&gt;| 1000   ------+--&gt;|         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
                                          +-----------+
                                     +---&gt;| ????????? |
                                     |    +-----------+
                                     |
    int **z @ 3000     int *y @ 2000 |    int x @ 1000
    +-----------+      +-----------+ |    +-----------+
    | 2000   ------+--&gt;| 7000   -----+ +-&gt;|         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
                                          +-----------+
                                     +---&gt;|         5 | (4+1)
                                     |    +-----------+
                                     |
    int **z @ 3000     int *y @ 2000 |    int x @ 1000
    +-----------+      +-----------+ |    +-----------+
    | 2000   ------+--&gt;| 7000   -----+ +-&gt;|         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).

答案2

得分: 3

First off, the x += 2 in f means absolutely nothing because of pass-by-value semantics and it's never used again, so let's get rid of it.

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

z is a pointer to y. When we dereference it and assign we're assigning to y in main. That y now points to some block of memory the right size for an int. The y that's our function argument is unchanged by this.

We now assign 4 to that chunk of memory, and then we increment it by 1. The y in main is now 5.

The y function argument still points to x in main, so when we dereference it and add 3, it's now 8.

The z in main still points to y, so that's 5 as well.

Thus 8, 5, 5 is printed.

Pass-by-value semantics in C are the real kicker here. I wonder if this would be easier to understand if we were looking at:

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

void f(int a, int* b, int **c)
{
    *c = malloc(sizeof(int));
    **c = 4;
    **c += 1;
    a += 2;
    *b += 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;
}
英文:

First off, the x += 2 in f means absolutely nothing because of pass-by-value semantics and it's never used again, so let's get rid of it.

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

z is a pointer to y. When we dereference it and assign we're assigning to y in main. That y now points to some block of memory the right size for an int. The y that's our function argument is unchanged by this.

We now assign 4 to that chunk of memory, and then we increment it by 1. The y in main is now 5.

The y function argument still points to x in main, so when we dereference it and add 3, it's now 8.

The z in main still points to y, so that's 5 as well.

Thus 8, 5, 5 is printed.

Pass-by-value semantics in C are the real kicker here. I wonder if this would be easier to understand if we were looking at:

#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;

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

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

huangapple
  • 本文由 发表于 2023年6月15日 07:33:41
  • 转载请务必保留本文链接:https://go.coder-hub.com/76478205.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定