指向指针值的指针不打印

Pointer to pointer value not printing

我是 C 编程的新手,最近学习了指针。我写了一些让我感到困惑的代码。我试图做出可能的解释,但似乎不正确。

这是我的代码:

#include <stdio.h>

int main() {
    int x = 5;
    int* p = &x;
    int*** q = &p; 
    printf("%u\n", *p);
    printf("%u\n", *q);
    printf("%u", ***q);
    return 0;
}

我所做的是,我已经声明了指向 x 的指针 p,然后声明了指向指针 p 本身的指针 q。我正在观看的视频中,首先有一个 **q 指向 p,当我试图取消引用它时,我得到了我能够理解它为什么以及如何这样做的价值。

现在,我想将 **q 更改为 ***q,当我尝试取消引用它时,它打印出:

5
// the address
// and then a new line

你能告诉我为什么会这样吗?向指针添加更多星星是什么意思?

一般规则是指向 int with n-1 * 的指针应该是 with n *(或任何其他类型),并且指针指向 int with n-1 stars

例如,让我们看一下 int,n = 1,所以指向它的指针应该是 1 *,所以你有一个指针,如果你取消引用它,你将得到一个 int 类型。

所以在你的例子中,我们有一个 int* 所以指向它的指针应该是 int**。 这里有一个指针,如果你取消引用它,你将得到一个 int* 类型。

编辑:添加更多解释为什么会出现空行。

请注意,*z 只是告诉编译器获取 z 中的值并将其用作地址,因此如果 z 中的值为 1000,它只是查看地址 1000 并查看其中的内容。在您的示例中,编译器会警告您出现问题,但如果您想这样做,请继续。

正如我们所解释的,当你执行 *q 时你得到 p,当你执行 **q 时你得到 x,所以当你执行 ***q 时你得到地址 5 的值,它与 * 相同5.

所以地址 5 中的值是未知的,在好的情况下我们可能会遇到分段错误,但我们可以得到任何东西,但行为已定义为您的示例。

编辑 2:仅当地址 5 是 int 的有效地址时才定义行为,如果不是这种情况,则生成程序集可能未定义

我们可以查看生成的程序集(使用-O2编译,只打印***q并删除了一些不感兴趣的行)

main:
.LFB11:
        movl    $.LC0, %edi
        movl    , 12(%rsp)
        movq    12(%rsp), %rax
        movl    (%rax), %esi
        xorl    %eax, %eax
        call    printf

LCO是字符串,esi是***q的值,可以看出esi是我们预期的地址5里面的值