为什么在C中传递结构参数时使用双指针?
我正在编写一些C代码来实现基本的堆栈数据结构操作,如push、pop等。 我正在使用堆栈的链表实现。 在这个实现中,每次我将一个值推入到“卡住”节点中时,我都会创建一个新节点,并将其设置为链接列表的头节点。因此,这涉及到更改头部节点的引用为什么在C中传递结构参数时使用双指针?,c,pointers,linked-list,C,Pointers,Linked List,我正在编写一些C代码来实现基本的堆栈数据结构操作,如push、pop等。 我正在使用堆栈的链表实现。 在这个实现中,每次我将一个值推入到“卡住”节点中时,我都会创建一个新节点,并将其设置为链接列表的头节点。因此,这涉及到更改头部节点的引用 void push(stack **t, int ele) { stack *new, *temp; temp=*t; new=(stack *)malloc(sizeof(stack)); if(new==NULL) { printf("\n sta
void push(stack **t, int ele)
{
stack *new, *temp;
temp=*t;
new=(stack *)malloc(sizeof(stack));
if(new==NULL)
{
printf("\n stack overflow");
return;
}
new=(stack *)malloc(sizeof(stack));
new->val=ele;
new->next=*t;
*t=new;
}
如果我使用单指针编写类似的代码,那么它将是这样的
void push(stack *t, int ele)
{
stack *new, *temp;
temp=t;
new=(stack *)malloc(sizeof(stack));
if(new==NULL)
{
printf("\n stack overflow");
return;
}
new=(stack *)malloc(sizeof(stack));
new->val=ele;
new->next=t;
t=new;
}
在函数中,除此之外的所有步骤中,头节点(**t)都显示在分配的右侧
*t=new;
基本上,第一个代码将'new'分配给**t的指针,即*t,第二个代码将'new'分配给*t的指针,即t。
两者似乎都只需要将指向头部节点的单个指针指定为“new”,但只有第一个代码起作用,而第二个代码实际上并不修改头部节点的值
发生这种情况的原因是什么?为什么第二个代码的工作方式与第一个不一样?因为C中的所有内容都是通过值传递的。因此,如果需要为函数的参数指定一个新值,则必须添加一个间接级别。如果没有,则只接收本地副本,因此分配给该副本的任何值将仅在函数本身中可见 另一方面,不要在C中强制转换
malloc
的返回值。这是不必要的,会使您的代码混乱,并且可能会隐藏允许默认int的编译器的错误
在。。另一个旁注,而不是写以下内容:
new_stack = malloc(sizeof(stack));
改用这个:
new_stack = malloc(sizeof(*new_stack));
现在,如果
新堆栈的类型发生变化,您就不会有问题了。如果是单指针,那么
int addInBeginning(int *s)
{
... // add a node in the beginning of the linked list
}
int main()
{
int *t;
... // make t point to a linked list say t ---> 1 -> 2 -> 3
f(t);
}
最初,s和t指向同一个列表。但是当我们在开始添加一个节点时,s指向新节点,而t仍然指向它之前指向的节点。当push返回时,新节点无法从t访问
0 -> 1 -> 2 -> 3
^ ^
| |
s t
如果是双指针,s将指向t,而t又指向列表。所以所有指针操作都发生在原始指针t上
s ----> t ----> 0 -> 1 -> 2 -> 3
您需要修改传递给push()
的第一个堆栈元素的指针,因此需要一个指针类型的参数。在第二个函数中,t
的赋值在函数外部是不可见的。是不是在第二个代码中,函数只是复制指向堆栈的指针,并且函数执行的所有更改仅应用于副本?请注意,不要使用名为new
(或此
或删除
)你可能会认为你永远不会把C++转换成C++,但是如果这样做,你会通过避免C++的关键字来简化事情。编码这个。这些变量名似乎更简单。谢谢!!是的,gcc编译器似乎能检测出转换错误,但是,是的,替代代码显然更好