1

我试图了解打印代码时发生了什么。

我知道p[0]并且p[1]指向相同的东西,如果p[1]它有自己的 malloc,p[0][0]会导致 0,但它会导致 1。

我试图了解是什么导致它导致 1。所以这段代码的结果是:

1
2
1
2 

但我不确定如何。

编码:

#include <stdio.h>
#include <stdlib.h>
int main(void) {
    int i,j;
    int **p = (int **)malloc(2 * sizeof(int *));
    p[0] = (int *)malloc(2 * sizeof(int));
    p[1] = p[0];
    for(i = 0; i < 2; i++)
        for(j = 0; j < 2; j++)
            p[i][j] = i + j;
    printf("%d\n",p[0][0]);
    printf("%d\n",p[0][1]);
    printf("%d\n",p[1][0]);
    printf("%d\n",p[1][1]);
    return 0;
}
4

4 回答 4

4

q成为mallocin的结果p[0] = (int *)malloc(2 * sizeof(int));

然后,在分配 and 之后p[1] = p[0];,两者p[0]p[1]都是q

那么这个语句p[i][j] = i + j;就等价于q[j] = i+j;,不管i是 0 还是 1。

然后这些循环:

    for(i = 0; i < 2; i++)
        for(j = 0; j < 2; j++)
            p[i][j] = i + j;

i为 0时执行两次赋值:

q[0] = 0 + 0;
q[1] = 0 + 1;

i当为 1时有两个分配:

q[0] = 1 + 0;
q[1] = 1 + 1;

后两个覆盖前两个,所以结果是q[0]包含 1 和q[1]包含 2。

然后这段代码:

    printf("%d\n",p[0][0]);
    printf("%d\n",p[0][1]);
    printf("%d\n",p[1][0]);
    printf("%d\n",p[1][1]);

相当于:

    printf("%d\n",q[0]);
    printf("%d\n",q[1]);
    printf("%d\n",q[0]);
    printf("%d\n",q[1]);

所以它会打印 1、2、1 和 2。

于 2020-09-14T11:47:56.173 回答
2

这两个值都设置了两次,一次通过p[0][j],第二次通过p[1][j]。由于第二次i是 1,所以放入这些单元格的值是1 + j

于 2020-09-14T11:48:43.790 回答
1

代码解释与注释:

// allocating space for 2 pointers to int
// this emulates an array of pointers to int *p[2]
int **p = malloc(2 * sizeof(int *)); 

// allocating space for the first pointer, which will contain 2 ints
p[0] = malloc(2 * sizeof(int));  

// assigning the pointer p[0] or p + 0 to the pointer p[1] or p + 1
// both pointer are now pointing to the same memory location as you already established
// so there is no need to allocate memory for p[1] as it's already 
// pointing to a valid memory location
p[1] = p[0]; 

// assigning the values, there is a redundancy here the values are assigned twice 
// albeit different, 0 1 in the first iteration and rewritten in the second 1 2
for (i = 0; i < 2; i++)
    for (j = 0; j < 2; j++)    
        p[i][j] = i + j;

// the same result  could be achieved, with half of the iterations
// as both pointers point to the same location
for (i = 1; i < 2; i++) //i = 1
    for (j = 0; j < 2; j++)    
        p[i][j] = i + j;

// printing the values, note that these are the same values from the same location
// but retrieved with different pointers p[0] and p[1]
printf("%d\n", p[0][0]);
printf("%d\n", p[0][1]);
printf("%d\n", p[1][0]);
printf("%d\n", p[1][1]);

我还应该注意,malloc不需要强制返回。

于 2020-09-14T11:57:11.860 回答
0

指针p[1]被设置为指针的值p[0]

p[1] = p[0];

因此,由于这种动态内存分配,两个指针都指向具有两个元素的同一个数组

p[0] = (int *)malloc(2 * sizeof(int));

这些循环中的外部 for 循环

for(i = 0; i < 2; i++)
    for(j = 0; j < 2; j++)
        p[i][j] = i + j;

首先使用指针p[0],然后使用指向p[1]同一个数组的指针。所以外循环的第一次迭代可以完全忽略,因为在外循环的第二次迭代中,指向的数组被指针覆盖p[1]。所以循环可以只用一个循环重写

    for( j = 0; j < 2; j++)
        p[1][j] = 1 + j;

因此p[1][0]设置为1 + 0即即为1(在循环的第一次迭代中)并p[1][1]设置为1 + 1即即为2(在循环的第二次迭代中)

在这些对同一数组的调用中,printf使用指向同一数组的指针输出两次。p[0]p[1]

printf("%d\n",p[0][0]);
printf("%d\n",p[0][1]);
printf("%d\n",p[1][0]);
printf("%d\n",p[1][1]);

这些调用等同于调用

printf("%d\n",p[0][0]);
printf("%d\n",p[0][1]);
printf("%d\n",p[0][0]);
printf("%d\n",p[0][1]);

或喜欢

printf("%d\n",p[1][0]);
printf("%d\n",p[1][1]);
printf("%d\n",p[1][0]);
printf("%d\n",p[1][1]);
于 2020-09-14T12:01:33.263 回答