我正在研究二元搜索树,并定义了如下的结构。
typedef struct __bnode
{
Member data;
struct __bnode *left;
struct __bnode *right;
} BinNode;
和我遇到问题的功能是
static void SetBinNode(BinNode *n, const Member *x, const BinNode *left, const BinNode *right)
{
n->data = *x;
n->left = left;
n->right = right;
}
但我遇到了以下警告:
分配给' struct __bnode *'来自' const BinNode *' (又名' const struct __bnode *')丢弃限定符
我认为警告并不危险,但这是因为我错过了一些东西。
我错过了什么?
答案 0 :(得分:0)
您的代码会尝试将const BinNode *
隐式转换为BinNode *
,并放弃const
。这是不安全的,所以你会收到警告。
以下是此代码如何咬你:
// Let's assume 'typedef int Member;' for simplicity
const BinNode zero = { 0, NULL, NULL };
int main(void) {
BinNode node;
SetBinNode(&node, NULL, &zero, NULL);
node->left->data = 42;
return 0;
}
此处我们有一个全局zero
变量,即const
。
电话SetBinNode(&node, NULL, &zero, NULL);
很好; &zero
的类型为const BinNode *
,这正是函数原型所说的SetBinNode
。
node->left->data = 42;
编译也很好。 node->left
是BinNode *
; node->left->data
是Member
(即我们示例中的int
)。
但这项任务可能会崩溃。致电node->left
后,zero
指向SetBinNode
。因为zero
是const
,编译器可能会将它放在只读内存中。现在,node->left->data
的分配尝试修改const
变量,从而触发分段错误。
所有这些都是在没有编译器投诉的情况下发生的......除了SetBinNode
中的一行。
解决方案是将SetBinNode
的类型更改为
static void SetBinNode(BinNode *n, const Member *x, BinNode *left, BinNode *right)
即。删除const
。参数上的const
正在做出无法保留的承诺。即使函数本身不通过*left
或*right
进行写入,它仍然可以通过非const访问路径使对象可用,这可能会在以后引起麻烦。