3

我正在编写一些 C 代码来实现基本的 Stack 数据结构操作,如 push、pop 等。我正在使用堆栈的链表实现。在这个实现中,每次我将一个值推入卡住时,我都会创建一个新节点,并将其设置为我的链表的头节点。所以这涉及到改变头节点的引用。

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)出现在所有步骤的赋值的 RHS 上,但这个

 *t=new;

基本上,第一个代码将'new'分配给**t的指针,即*t,而第二个代码将'new'分配给*t的指针,即t。两者似乎都只需要将指向头节点的单个指针分配为“新”,但只有第一个代码有效,第二个代码实际上并没有修改头节点值。

发生这种情况的解释是什么?为什么第二个代码的工作方式与第一个代码不同?

4

2 回答 2

3

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

附带说明一下,不要malloc在 C 中强制转换返回值。这是不必要的,会使您的代码混乱,并且可以为允许默认 int 的编译器隐藏错误。

在..另一个旁注,而不是写类似的东西:

new_stack = malloc(sizeof(stack));

改用这个:

new_stack = malloc(sizeof(*new_stack));

现在,如果类型发生变化,您就没有问题了new_stack

于 2013-03-27T19:16:01.273 回答
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 又指向列表。所以所有指针操作都发生在原始指针 t 上。

s ----> t ----> 0 -> 1 -> 2 -> 3
于 2013-09-25T07:23:29.157 回答