为什么指向指针的指针与指向数组的指针不兼容?
好吧,我无法理解指向指针的指针与指向数组的指针。 考虑以下代码:
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”。但事实并非如此!
OK, I'm having trouble understanding pointers to pointers vs pointers to arrays.
Consider the following code:
char s[] = "Hello, World";
char (*p1)[] = &s;
char **p2 = &s;
printf("%c\n", **p1); /* Works */
printf("%c\n", **p2); /* Segmentation fault */
Why does the first printf work, while the second one doesn't?
From what I understand, 's' is a pointer to the first element of the array (that is, 'H').
So declaring p2 as char** means that it is a pointer to a pointer to a char. Making it point to 's' should be legal, since 's' is a pointer to a char. And thus dereferencing it (i.e. **p2) should give 'H'. But it doesn't!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您的误解在于
s
是什么。它不是指针:它是一个数组。现在,在大多数情况下,
s
计算结果为指向数组第一个元素的指针:相当于&s[0]
,指向'H 的指针'
。但这里重要的是,在计算s
时获得的指针值是一个临时的、短暂的值 - 就像&s[0]
一样。因为该指针不是永久对象(它实际上不是存储在
s
中的内容),所以您不能在它上创建指针到指针的指针。要使用指针到指针,您必须有一个真正的指针对象来指向 - 例如,以下内容就可以:如果您计算
*p2
,则告诉编译器加载p2
指向的东西并将其视为指向字符的指针。当 p2 实际上指向字符指针时,这很好;但是当你执行char **p2 = &s;
时,p2
指向的东西根本不是一个指针 - 它是一个数组(在这种情况下,它是一个由 13 个char
组成的块)。Your misunderstand lies in what
s
is. It is not a pointer: it is an array.Now in most contexts,
s
evaluates to a pointer to the first element of the array: equivalent to&s[0]
, a pointer to that'H'
. The important thing here though is that that pointer value you get when evaluatings
is a temporary, ephemeral value - just like&s[0]
.Because that pointer isn't a permanent object (it's not actually what's stored in
s
), you can't make a pointer-to-pointer point at it. To use a pointer-to-pointer, you must have a real pointer object to point to - for example, the following is OK:If you evaluate
*p2
, you're telling the compiler to load the thing thatp2
points to and treat it as a pointer-to-char. That's fine whenp2
does actually point at a pointer-to-char; but when you dochar **p2 = &s;
, the thing thatp2
points to isn't a pointer at all - it's an array (in this case, it's a block of 13char
s).据我了解,'s'是指向数组第一个元素的指针
不,s 是一个数组。它可以简化为指向数组的指针,但在此之前,它只是一个数组。指向数组的指针成为指向数组第一个元素的指针。 (是的,这有点令人困惑。)
char (*p1)[] = &s;
这是允许的,它是一个指向数组的指针,分配了数组的地址。它指向 s 的第一个元素。
char **p2 = &s;
这会生成一个指向指针的指针,并为其分配数组的地址。当它认为它是指向一个或多个字符的指针时,您为其分配一个指向 s 第一个元素(
char
)的指针。取消引用这是未定义的行为。 (在你的情况下是段错误)它们不同的证明在于
sizeof(char[1000])
(返回 1000 个字符的大小,而不是指针的大小),以及如下函数:当给定数组而不是指针时进行编译。
From what I understand, 's' is a pointer to the first element of the array
No, s is an array. It can be reduced to a pointer to an array, but until such time, it is an array. A pointer to an array becomes a pointer to the first element of the array. (yeah, it's kinda confusing.)
char (*p1)[] = &s;
This is allowed, it's a pointer to an array, assigned the address of an array. It points to the first element of s.
char **p2 = &s;
That makes a pointer to a pointer and assigns it the address of the array. You assign it a pointer to the first element of s (a
char
), when it thinks it's a pointer to a pointer to one or more chars. Dereferencing this is undefined behavior. (segfault in your case)The proof that they are different lies in
sizeof(char[1000])
(returns size of 1000 chars, not the size of a pointer), and functions like this:which will compile when given an array, but not a pointer.
这是有效的示例,加上指针地址的打印输出,使事情变得简单易懂:
Here's the sample that works, plus printouts of pointer addresses to make things simple to see: