*root 和 **root 有什么区别?

what is the difference between *root and **root?

我正在迭代一个树数据结构,它有一个指向其根的指针,如下所示-

struct node *root;

当我必须将此根的引用作为参数传递给函数时....我必须像这样传递它-

calcHeight(&root);
-
-
-
//somewhere

int calcHeight(struct node **root)      // function defination is this

我的问题是 - 为什么我们需要将“root”指针作为 &root 传递?我们不能像 --

struct node *root;
calcHeight(root);
int calcHeight(struct node *root);

// 编辑

void someFunct(int *arr){
    printf("arr2 inside someFunct is %d\n",arr[2]);
    arr[2]=30;
}

int main()
{
    int *arr=(int*)calloc(10,sizeof(int));
    printf("arr[2] is %d\n",arr[2]);

    someFunct(arr);
    printf("arr[2] finally is %d\n",arr[2]);
    return 0;
}

在这种情况下,即使我没有传递 arr 的地址,main 函数中的 arr 也会被修改。 我得到的事实是,对于结构和单值变量,我们必须像 someFunct(&var) 一样传递地址,但这对于数组来说不是必需的吗?对于数组,我们写 someFunct(arr)
但我不明白这背后的原因?

struct node * 是指向 struct node.
的指针 struct node ** 是指向 struct node.

的指针

传入 struct node ** 的原因可能是该函数需要修改 struct node * 实际指向的内容 - 这对于名为 calcHeight 的函数来说似乎很奇怪。如果它是 freeNode 它可能是有道理的。示例:

void freeNode(struct node **headp) {
    free(*headp);
    *headp = NULL; // make the struct node * passed in point at NULL
}

Demo

另一个原因可能是为了使接口保持一致,因此总是需要为支持struct node的函数中的所有函数提供struct node ** - 不仅是那些真正需要改变 struct node * 指向的内容的人。


关于添加的// EDIT部分:

在这种情况下,没有理由发送指针到指针。如果不需要更改实际指针,只需要将指针的发送进来即可。

内存布局示例:

Address    What's stored there
+-----+
|  +0 |     uint64_t   ui1 = 1     <--+
+-----+                               |
|  +8 |     uint64_t   ui2 = 2        |
+-----+                               |
| +16 |     uint64_t*  p   = &ui1  ---+
+-----+

现在,如果函数只需要一个 uint64_t 值,您可以将 ui1ui2*p 发送到该函数。

void someFunc(uint64_t val) { ++val; ... }

此函数对 val 所做的更改对函数的调用者不可见。

如果函数应该能够进行函数调用者可见的更改,请发送指针:

void someFunc(uint64_t *valp) { *valp = 10; }

someFunc(&ui1);someFunc(p);调用它会改变ui1并给它赋值10。

如果您有一个指针并想要更改它实际指向的内容,这就是您最初的问题所问的内容,您需要发送一个指向该指针的指针:

void someFunc(uint64_t **valpp) { *valpp = &ui2 }`

如果你用 someFunc(&p) 调用它(其中 p 当前指向 ui1)你会发现 函数调用之后, p 将指向 ui2:

+-----+
|  +0 |     uint64_t   ui1 = 1
+-----+
|  +8 |     uint64_t   ui2 = 2     <--+
+-----+                               |
| +16 |     uint64_t*  p   = &ui2  ---+
+-----+

因为在 calcHeight 中您是按值传递参数。如果你想通过root修改指向的值,你需要传递指针的地址。

第一个是指向结构节点的指针。

struct node *root;

定义root为一个可以存储节点地址的变量

第二个是指向结构体节点的指针。

struct node **root;

定义 root 为变量,它可以存储另一个具有节点地址的变量的地址。

为什么我们需要将“root”指针作为 &root 传递?

calcHeight(&root);

C 按值传递参数,而不是按引用传递。所以,你必须通过root的地址来修改root的值。