【问题标题】:What does assignment of a pointer element to another pointer element in the array mean?将指针元素分配给数组中的另一个指针元素是什么意思?
【发布时间】:2019-12-17 05:16:04
【问题描述】:

我不太明白将一个指针分配给另一个指针是什么意思?这里**p是一个指针数组/二维数组,然后p[0]被分配给p[1],它们都指向同一个地址吗?

#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",p[0][0]);
    return 0;
}

我希望输出为 0,但实际上是 1,为什么?

【问题讨论】:

  • p 是一个指针数组。因此,您将指针从 p[0] 分配给 p[1]。因此,它们都指向 相同的 区域,该区域的大小为 2 个整数。对我来说看起来一团糟。
  • p 不是数组(或者你说的**p),指针和数组有很大的不同

标签: c loops for-loop pointers assignment-operator


【解决方案1】:

p[0]p[1] 两个指针在表达式语句后具有相同的值

p[1] = p[0];

因此,在使用表达式 p[1] 的地方,它可以替换为表达式 p[0],因为这两个表达式具有相同的值,反之亦然。

在这个循环中

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

i 等于1 并且j 等于0 时(假设p[1] 等于p[0]。)所以p[1][0] 等于p[0][0] 并且等于到i + j,即1

其实就是这个循环

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

相当于循环

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

因此,外循环的第二次迭代会在第一次迭代后重写存储在p[0][0]p[0][1] 中的值。

在第二次迭代中,i 等于 1。因此,对于 [0, 1] 范围内的 j,我们有

p[0][0] = i + j (when i == 1 and j == 0 ) = 1

p[0][1] = i + j (when i == 1 and j == 1 ) = 2

【讨论】:

    【解决方案2】:

    它们都指向同一个地址吗?

    是的。

    以下是对您的程序的修改,应该更清楚:

    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;
        for(i = 0; i < 2; i++) {
            printf("%d (%p)\t", i, p[i]);
            for(j = 0; j < 2; j++)
                printf("%d ", p[i][j]);
            printf("\n");
        }
        return 0;
    }
    

    这里我们打印出指针值p[0]p[1],以及“二维”数组的所有四个单元格——除了,是的,实际上只有两个单元格,每个单元都执行双重任务两行。在我的系统上,这会打印出来

    0 (0x7f92ca402710)  1 2 
    1 (0x7f92ca402710)  1 2 
    

    你可以清楚的看到两个指针是一样的。

    在记忆中,我们可以这样想:

       +-------+
    p: |   *   |
       +---|---+
           |
           v
       +-------+           +---+---+
       |   *----------+--->| 1 | 2 |
       +-------+     /     +---+---+
       |   *--------'
       +-------+
    

    另一方面,如果您调用 malloc 三次,而不是两次,如下所示:

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

    你会得到一个更像这样的打印输出:

    0 (0x7fb747402710)  0 1 
    1 (0x7fb747402720)  1 2 
    

    你会在内存中得到这样的图片:

       +-------+
    p: |   *   |
       +---|---+
           |
           v
       +-------+           +---+---+
       |   *-------------->| 0 | 1 |
       +-------+           +---+---+
       |   *--------.
       +-------+     \     +---+---+
                      '--->| 1 | 2 |
                           +---+---+
    

    【讨论】:

      【解决方案3】:

      我不太明白分配一个指针是什么意思 另一个指针?这里 **p 是指针数组/二维数组,然后是 p[0] 分配给p[1],它们都指向同一个地址吗?

      是的。但是从概念上来说,忽略p[0]p[1] 的值的重要性(这些值是指针,以及这些值指向什么)可能更有用,而是关注以下事实:赋值,它们的值是相同的。然后这些值指向同一事物。

      请注意,我有意选择了区分存储位置指示符(例如“p[1]”)和这些位置的内容的措辞——它们的值。我们经常使用模糊区分的语言,因为以这种方式准确地说出来很麻烦,但您必须在头脑中保持区分。形式上,它不是 表达式 p[1] 甚至它指定的存储位置是一个指针,而是存储在那里的值。赋值运算符将该值复制到另一个存储位置,因此很自然,如果另一个存储位置的内容根据相同的数据类型进行解释,那么它们的含义与原始位置相同。

      我希望输出为 0,但实际上是 1,为什么?

      因为在设置了p[1] = p[0] 之后,表达式p[1][0] 指定了与p[0][0] 相同的对象。分配p[1][0] = 1 + 0 后,您可以从p[1][0]p[0][0] 读回结果值(1)。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-01-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-16
        相关资源
        最近更新 更多