我有一个学校项目,我需要使用链表对数字进行排序。我在初始化链表时遇到了一些麻烦,有人给了我解决方案,但我真的不明白一行上发生了什么,我想要一些启发。
这是完整的功能:
void stack_ini(t_lst **list_ptr, char **nbr)
{
for (; *nbr; ++nbr)
{
// Create a new node.
t_lst *node = malloc(sizeof(t_lst));
node->content = ft_atoi(*nbr);
node->next = NULL;
// Insert it into the list.
*list_ptr = node;
list_ptr = &node->next;
}
}
要完成,下面是t_lst结构:
typedef struct s_lst
{
int content;
int position;
int index;
struct s_lst *next;
} t_lst;
我几乎理解最后一行之前发生的一切:
list_ptr = &node->next;
我不明白为什么我需要将list_ptr分配给节点>next的地址。节点>下一个不是应该未初始化并因此引发段错误吗? 另外,如果节点和list_ptr未分配给它们的...->next,难道不应该像重写它们的当前值一样吗?
对不起我的英语,谢谢你的回答。
我几乎理解在最后一次之前发生的一切 线:
list_ptr = &node->next;
我不明白为什么我需要将list_ptr分配给节点>next的地址。 节点>下一个不是应该未初始化,从而引发 段错误 ?
不。node->next
显式初始化为空指针。 此外,即使它没有被初始化,它的地址(&node->next
)也是很好的定义。无论初始化状态或node->next
的值如何,都可以计算该值。
在这一点(*node->next
)取消引用node->next
将产生未定义的行为,因为它的值是一个空指针,这很可能表现为程序因段错误而崩溃,但没有执行取消引用。
此外,如果节点和list_ptr未分配给其 ...->接下来,不应该像覆盖它们的当前值一样吗?
添加节点后,list_ptr
设置为指向该节点的next
成员,其值最初为 null。 然后,当创建下一个节点时,通过list_ptr
分配给(当时)上一个节点的next
的指针。 之后,循环重复,从更新list_ptr
开始,指向最近添加的节点的next
成员。
所以是的,通过list_ptr
赋值确实会替换它指向的指针的值,但对于每个节点最多发生一次,因为在更新之后,list_ptr
本身会更新为指向不同节点的next
成员。
假设最初指向 main 中声明的头节点的指针设置为 NULL,如下所示
t_lst *head = NULL;
此指针通过指向它的指针间接地通过引用传递到函数stack_ini
。所以函数的声明是这样的
void stack_ini(t_lst **list_ptr, char **nbr);
^^^^^^^^^^^^^^^^
第一次取消引用参数list_ptr
就像*list_ptr
我们可以访问在 main 中声明的原始指针head
并且可以更改它。
所以在函数的第一次迭代中 for 循环这个语句
*list_ptr = node;
将原始指针head
设置为指向新分配节点的指针node
的值。
然后将参数list_ptr
设置为数据成员的地址head->next
相当于在此语句中使用node->next
list_ptr = &node->next;
因此,现在指针list_ptr
指向可以在 for 循环的下一次迭代中更改的数据成员next
。
初始化数据成员node->next
node->next = NULL;
这就是这句话
list_ptr = &node->next;
您没有在指针list_ptr
旁边分配数据成员节点>的值。相反,指针list_ptr
指向当前创建的节点的数据成员next
,并且使用list_ptr
可以在 for 循环的下一次迭代中更改该数据成员的值。