2013-03-27 72 views
3

我正在编写一些C代码来实现像push,pop等基本的栈数据结构操作。 我使用堆栈的链表实现。 在这个实现中,每次我将一个值推入卡住时,我创建一个新节点,并将其设置为我的链接列表的头节点。所以这涉及到改变头节点的引用。为什么我们在C中传递Structure参数时使用双指针?

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; 

} 

在功能方面,头节点(**吨)出现在赋值的RHS在所有步骤中,但这

*t=new; 

基本上所述第一代码分配“新”到的**吨的指针,也就是* T,和第二代码受让人“新”到的* T的指针,也就是吨。 两者似乎都只需要指向头节点的单指针指定为“新”,但只有第一个代码有效,而第二个实际上并不修改头节点值。

这是怎么发生的?为什么第二个代码的工作方式与第一个类似?

+1

您需要修改指向传递给'push()'的第一个堆栈元素的指针,因此您需要一个指向指针类型的指针参数。在第二个函数中,赋值给't'在函数外部是不可见的。 – 2013-03-27 18:52:56

+0

在第二个代码中,函数是否简单地将指针复制到堆栈,并且该函数执行的所有更改仅应用于副本? – 2013-03-27 18:57:22

+2

请注意,请不要使用名为'new'(或'this'或'delete')的变量。你可能会认为你永远不会将你的代码转换成C++,但是如果发生这种情况,你现在可以通过避免使用C++的关键字来让事情变得更容易。 – mah 2013-03-27 18:57:37

回答

3

因为C中的所有内容都是按值传递的。因此,如果您需要为函数的参数分配新值,则必须添加一个间接级别。如果你不是简单地接收本地副本,那么分配给该副本的任何值都将仅在该函数本身中可见。

请注意,不要在C中返回malloc的返回值。这是不必要的,您编码的混乱,并且可以隐藏允许默认int的编译器的错误。

在..另一个方面说明,而不是写是这样的:

new_stack = malloc(sizeof(stack)); 

使用这个代替:

new_stack = malloc(sizeof(*new_stack)); 

现在你没有问题,如果的new_stack不断变化的类型。

+0

谢谢!是的,海湾合作委员会编译器似乎检测到铸造错误,但是是替代代码是肯定似乎更好 – 2013-03-27 19:21:32

2

在单指针的情况下,说

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上。

s ----> t ----> 0 -> 1 -> 2 -> 3 
相关问题