为什么指向指针的指针与指向数组的指针不兼容?

时间:2011-10-27 23:07:05

标签: c arrays pointers

好的,我无法理解指针与指向数组指针的指针。 请考虑以下代码:

char s[] = "Hello, World";
char (*p1)[] = &s;
char **p2 = &s;
printf("%c\n", **p1); /* Works */
printf("%c\n", **p2); /* Segmentation fault */

为什么第一个printf工作,而第二个不工作?

据我所知,'s'是指向数组第一个元素的指针(即'H')。 因此将p2声明为char **意味着它是指向char的指针。使它指向's'应该是合法的,因为's'是指向char的指针。因此取消引用它(即** p2)应该给出'H'。但事实并非如此!

3 个答案:

答案 0 :(得分:11)

你的误解在于s是什么。 不是指针:它是一个数组。

现在在大多数情况下,s计算指向数组第一个元素的指针:等同于&s[0],指向'H'的指针。但重要的是,在评估s时得到的指针值是一个临时的短暂值 - 就像&s[0]一样。

因为该指针不是永久对象(它实际上不是存储在s中的对象),所以不能在其上创建指向指针的指针。要使用指向指针的指针,必须有一个指向的实际指针对象 - 例如,以下是正常的:

char *p = s;
char **p2 = &p;

如果你评估*p2,你告诉编译器加载p2指向的东西并将其视为指向char的指针。当p2确实指向指向char的指针时,这很好;但是当你执行char **p2 = &s;时,p2指向的东西根本不是指针 - 它是一个数组(在这种情况下,它是一个13 char s的块)。

答案 1 :(得分:1)

From what I understand, 's' is a pointer to the first element of the array
不,s是一个数组。它可以简化为指向数组的指针,但在此之前,它是一个数组。指向数组的指针成为指向数组第一个元素的指针。 (是的,这有点令人困惑。)

char (*p1)[] = &s; 这是允许的,它是指向数组的指针,分配了数组的地址。它指向s的第一个元素。

char **p2 = &s;
这使得指针指向并为其指定数组的地址。当它认为它是指向一个或多个字符的指针时,为它指定一个指向s的第一个元素(a char)的指针。取消引用这是未定义的行为。 (在你的情况下为segfault)

它们不同的证据在于sizeof(char[1000])(返回1000个字符的大小,而不是指针的大小),并且函数如下:

template<int length>
void function(char (&arr)[length]) {}

当给定数组时将编译,但不是指针。

答案 2 :(得分:1)

以下是可用的示例,以及指针地址的打印输出,以便于查看:

#include <stdio.h>
char s[] = "Hello, World";
char (*p1)[] = &s;
char *p2 = (char*)&s;

int main(void)
{
   printf("%x %x %x\n", s, p2, *p2);
   printf("%x\n", &s);    // Note that `s` and `&s` give the same value
   printf("%x\n", &s[0]);
   printf("%c\n", **p1); 
   printf("%c\n", *p2);
}