指向指针的指针与指针之间的区别

5

我在尝试使用双指针(指向指针的指针)并想要正确理解它。我正在尝试下面的代码:

#include<stdio.h>

int main()
{
    int y = 5;
    int *p = &y;
    int *q = &p;

    printf("\n\n %p %p %p %p %d\n\n",q,&p,p,*q,*p);

    return 0;

 }

现在,在上面的代码中,p是指向y的指针,q是指向p的指针。我故意没有使用双重指针(**q)来检查会发生什么。编译器给了我一个警告,指出不兼容的指针类型。当我执行代码时,我理解q是指向p的指针,因此它包含p的地址,但*q并没有给我p中包含的值,即y的地址,而是得到了一些垃圾值。是因为我没有将q声明为双重指针吗?有人可以解释一下为什么*q正好是一些奇怪的值吗?

q不是指向p的指针。 - Eugen Rieck
你违反了关于q的规则,因此出现了警告,但我承认我不确定在这个例子中应该打印什么。可能是一个标准问题违规,或者导致未定义的行为?我会让其他人来解决这个问题。 - Michael Dorgan
@EugenRieck 那么 q 指向哪里? - cdhowie
1
当你提出这样的问题时,故意使用违反C标准的代码,你必须指定你正在使用哪个C实现(编译器名称、版本、目标平台、编译使用的开关等)。你还应该显示你收到的确切输出。显然,仅根据C标准是没有答案的,但有时候可以根据你特定的实现方式得出答案。但如果你不提供必要的信息,就无法给出这些答案。 - Eric Postpischil
4个回答

3
我得到了一些垃圾值。是因为我没有将q声明为双指针吗?基本上是的:因为您将q声明为指向int的指针,解引用操作*q认为地址是一个int。当将该int作为指针发送到%p时,会发生未定义的行为。请注意,即使在指针的表示与int完全相同的平台上,行为仍将保持未定义。这就是未定义行为的危险本质:有时它会“错误地”运行。

p,*q和&y都指向相同的地址;q和&p也指向相同的地址 - user195488
1
@0A0D 就编译器而言,这并不正确:对于编译器来说,*q 并没有 "指向" 任何东西,因为它是一个 int - Sergey Kalinichenko

1
在您的示例中,p 是指向 int 的指针,这意味着 &p 是指向指针的指针。因此,q 应声明为 int**
根据我下面的评论... 您错误地声明了 q... 因此,*q 是一个整数,而不是一个指针,并且您正在将一个整数传递到 printf() 中,它正在寻找一个内存地址... 在此之后几乎任何事情都是未定义的行为。

1
他理解了这个问题,但是想知道为什么打印出的值是垃圾。 - Michael Dorgan
1
另外,printf() 中的 *q 需要改为 **q - Brendan
因为我给出的答案... q 被错误地声明,因此编译器将 *q 视为 int 而不是 int*,这意味着一个整数而不是指向整数的指针被传递给了 printf - K Scott Piel

1
这行代码不正确。
 int *q = &p;

&p是指向一个整数(y)的指针(p)的地址

将其分配给一个指向整数(q)的指针将进行重新解释

*q将把p的地址解释为整数。这与y的内容(=5)不同


1

有人能解释一下为什么我得到了一些奇怪的值,如 *q 吗?

存在几个问题:

  • 首先,使用 *q 时,您试图将指针解释为 int。这是无效的。
  • 其次,您的 printf() 格式说明符与第五个参数的类型不匹配。

在某些平台上(包括我正在打字的计算机),指针比 int 更宽。如果我在我的电脑上运行您的代码,我会得到:

0x7fff5ef94ad8 0x7fff5ef94ad8 0x7fff5ef94ae4 0x5ef94ae4 5

这里,64位指针被截断为32位的int。因此,只有指针的低位部分被显示出来。然而,由于您的代码行为未定义,它可能会以其他方式失败。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接