使用指向指针的指针访问结构成员

accessing struct members using pointer to pointer

我有一个如下所示的程序,当我尝试使用指向指针的指针访问结构成员时,它说表达式必须具有指向 class 类型的指针。请告诉我如何使用指向指针的指针访问结构对象的数据元素

#include "stdafx.h"
#include<iostream>
struct Node{
    int data;
    Node* next;
};

void addnode(Node** node, int val)
{
    if (node == NULL){
        *node = new Node();
        *node->data = val;

    }
}



int _tmain(int argc, _TCHAR* argv[])
{
    Node* node;
    addnode(&node, 10);
    return 0;
}

*node->data = val;等同于*(node->data) = val;,但是你想要的是(*node)->data = val;(所以你需要加上括号)。

*node->data = val;中涉及到3个运算符。

  • operator* 取消引用
  • operator->访问会员
  • operator=做作业

这些发生的顺序是什么?根据 operator precedence 其中指出:

Precedence Operator
2 operator->
3 operator*
16 operator=

node->data 将首先发生,然后结果将被取消引用 - 因此您在左侧有 *(node->data)

您需要先取消引用 node,然后可以使用 (... ) 覆盖优先规则:

(*node)->data = val;

另请注意,您的原始 Node* 未初始化,读取它(就像您在 if(node == NULL) 中所做的那样)将导致程序具有未定义的行为。初始化为 nullptr:

Node* node = nullptr; // here
addnode(&node, 10);

问题是由于运算符优先级,语句*node->data = val;等同于:

*(node->data) = val;

上面的语句不起作用,因为取消引用 node 会给我们 Node*,它没有任何名为 data 的成员,因为它是 non-class 类型。 要 解决 这个问题,您需要通过在 *node 周围添加括号来覆盖此行为,如下所示:

(*node)->data = val;

另外,main里面的变量node是未初始化的。您应该如下所示对其进行初始化:

 Node* node = nullptr;

这是操作顺序。它需要是 (*node)->data = val。另请注意, if 语句与您想要的相反: *node 不是错误,您需要测试 nodenot null 不是说它是 null。

对于初学者,您需要在 main

中初始化指针节点
Node* node = nullptr;

其次是这个表达式

*node->data = val;

相当于

* ( node->data ) = val;

由于运算符的优先级,因为包括运算符 -> 在内的后缀运算符的优先级高于解引用运算符 *.

等一元运算符

至少你需要写

( *node )->data = val;

但是无论如何这个函数都没有意义。

如果你需要在单向链表的开头添加一个新节点,那么函数将如下所示

void addnode(Node** node, int val)
{
    *node = new Node { val, *node };
}

或者不使用像

这样的双指针
void addnode( Node* &node, int val)
{
    node = new Node { val, node };
}

在这种情况下函数被调用为

addnode(node, 10);

如果你想将一个新节点附加到 singly-linked 列表的末尾,那么在这种情况下,函数可以类似于

void addnode(Node** node, int val)
{
    while ( *node ) node = &( *node )->next;
    *node = new Node { val, *node };
}