为什么* pp [0]等于** pp

时间:2016-01-26 23:39:03

标签: c pointers dereference

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

#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,但那不是因为程序的输出是:

输出

abc, abc

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

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

3 个答案:

答案 0 :(得分:5)

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

所以**pp的确意味着**&pp[0]

&pp[0]pp[0]的地址,因此*&pp[0]仅相当于pp[0],因此**&pp[0]相当于*pp[0]。< / p>

答案 1 :(得分:2)

无论你正在处理什么类型的指针,

pp [0]始终与* pp相同。

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

答案 2 :(得分:2)

  

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

这是你的理由,但可以理解。在C中,赋值的右侧,或者通常是对左值(vulgo:variable)的评估,更确切地说是左值到右值的转换,已经是解除引用的!例如,{ {1}}有效解除引用int i, j=0; i=j;; j是地址常量,并且赋值涉及存储在其中的值j的值,因此赋值为j。其他语言,如Algol68,更精确:一个人会有效地写i=0,这完全合情合理(pi现在指向i)。

这就是为什么当您使用int i; int *pi = i;明确取消引用pp[0] 时,您有效地取消引用它两次:首先,您在地址0x2000的内容中查找 < / em>,这是0x1000,然后你取消引用,以便读取0x1000的内存。