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

Met*_*eta 12 c arrays pointers

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

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

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

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

caf*_*caf 12

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

现在在大多数上下文中,s求值为指向数组第一个元素的&s[0]指针:等效于指向该数组的第一个元素'H'.这里重要的是,在评估时得到的指针值s是一个临时的,短暂的值 - 就像&s[0].

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

char *p = s;
char **p2 = &p;
Run Code Online (Sandbox Code Playgroud)

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