【问题标题】:why is *pp[0] equal to **pp为什么 *pp[0] 等于 **pp
【发布时间】:2016-05-03 17:48:16
【问题描述】:

所以我试图弄清楚指针,我阅读了一些关于指针指针的帖子,但我仍然无法弄清楚为什么这个程序可以毫无问题地运行

#include <stdio.h>
#include <assert.h>

int main(){
    char* p = "abc";

    char** pp[2];
    pp[0] = &p;
    assert(*pp[0]==**pp);

    printf("Comparison: %s, %s\n",**pp, *pp[0]);

    return 0;
}

据我所知,内存看起来像这样

Memory Address (hex)    Variable name    Contents
1000                                     'a' == 97 (ASCII)
1001                                     'b' == 98
1002                                     'c' == 99
1003                                     0
...
2000-2003               p                1000 hex
...
3000-3003               pp[0]            2000 hex

在这一点上,假设我的记忆是正确的...... 我希望 *pp[0] 进入记忆并说...

所以 pp[0] 指向 p 的地址,即 0x2000,通过取消引用,我希望得到地址 0x2000 的内容,在我看来这意味着我会得到 0x1000,但这不是case,因为程序的输出是:

输出

abc, abc

在 **pp 的情况下,我认为它首先取消引用 pp ,这将为我们提供 pp 指向的任何内容,这意味着 0x2000(即 0x1000)的内容,然后通过再次取消引用,我们得到地址 0x1000

为什么他们会是平等的?我在哪里错过了什么

【问题讨论】:

  • 因为pp 可以是&amp;pp[0] 的缩写,而**&amp;pp[0] 显然与*pp[0] 相同(因为*&amp;xx 相同,只要它有效)。

标签: c pointers dereference


【解决方案1】:

所以 pp[0] 指向 p 的地址,即 0x2000,通过取消引用,我希望得到地址 0x2000 的内容

那是你的推理偏差,但可以理解。在 C 中,赋值的右侧,或者通常是对左值(vulgo:变量)的评估,更准确地说是左值到右值的转换,已经是取消引用!例如,@ 987654321@ 有效地取消引用jj 是一个地址常量,赋值关系到存储在那里的值,j 的值,所以赋值等于i=0。其他语言,如 Algol68,更精确:可以有效地写成 int i; int *pi = i;,这完全有道理(pi 现在指向 i)。

这就是为什么当您使用*pp[0] 取消引用pp[0] 显式 时,您实际上是在两次有效地取消引用它:首先您查看地址0x2000 的内容,这是 0x1000,然后你取消引用它以便读取 0x1000 处的内存。

【讨论】:

    【解决方案2】:

    pp[0] 总是和 *pp 一样,不管你处理的是什么类型的指针。

    鉴于方括号的高运算符优先级,*pp[0] 与 *(pp[0]) 相同......根据上面的句子,它与 *(*pp) 相同,这与**pp相同。 Q.E.D..

    【讨论】:

      【解决方案3】:

      在大多数情况下,如果您有一个数组a,则a&amp;a[0] 的缩写。 (有一些例外,例如sizeof a&amp;a)。

      所以**pp 真正的意思是**&amp;pp[0]

      &amp;pp[0]pp[0]的地址,所以*&amp;pp[0]就相当于pp[0],所以**&amp;pp[0]就相当于*pp[0]

      【讨论】:

      • 这个答案很有意义,这可能是我将来会如何看待它,但我的推理更多地遵循@Peter,其中提到 *pp[0] 有效地取消引用两次,否则它赢了根据我写的内容对我来说没有意义,我希望两个答案没有冲突,感谢您的帮助
      • @OmarMuñoz 如果pp 是一个数组,pp[0] 实际上会取消对引擎盖下的任何内容的引用。 (嗯,它不会像访问任何其他变量那样取消引用)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-09-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-09-28
      • 1970-01-01
      相关资源
      最近更新 更多