使用指向指针的指针访问结构成员
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
不是错误,您需要测试 node
是 not 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 };
}
我有一个如下所示的程序,当我尝试使用指向指针的指针访问结构成员时,它说表达式必须具有指向 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
不是错误,您需要测试 node
是 not 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 };
}