【问题标题】:Pointer passed in to function not reassigning传入函数的指针未重新分配
【发布时间】:2016-10-24 20:45:49
【问题描述】:

所以我正在尝试实现一个链表堆栈,它接受 char 参数并将它们添加到链接列表中,并将其 ascii 代码作为节点的值。

我将我的 nstack 指针传递给我的 push 函数并将它重新分配给 new_node 以创建一个新的顶部,但我的 push 函数似乎没有重新分配我的 nstack 节点 - 它只是打印最初初始化的 nstack价值。为什么不重新分配 nstack?

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct list_node {
    int element;
    struct list_node * pnext;
};

void push(struct list_node *operators, int e);

int pop(struct list_node *operators);


int main(int argc, char *argv[]) {
    int newvalue = (int)argv[1][0];
    struct list_node * nstack = (struct list_node*)malloc(sizeof(struct list_node));

    nstack->element = newvalue;
    nstack->pnext = NULL;
    int i;  
        for (i = 2; i < argc; i++) {
            push(nstack, (int)argv[i][0]);
        }
    printf("top: %d\n", nstack->element);
}

void push(struct list_node *nstack, int e) {
    struct list_node * new_node = (struct list_node*)malloc(sizeof(struct list_node));
    new_node->pnext = nstack;
    new_node->element = e;
    nstack = new_node;
}

【问题讨论】:

  • C11 标准草案 n1570:6.5.2.2 函数调用 4 参数可以是任何完整对象类型的表达式。在准备调用函数时,会评估参数,并为每个参数分配相应参数的值。 93) 函数可以改变其参数的值,但这些改变不会影响参数的值。另一方面,可以传递一个指向对象的指针,函数可能会改变指向的对象的值。
  • void push(struct list_node *nstack, int e) 可以是struct list_node *push(struct list_node *nstack, int e),它返回一个由调用者分配的指针。所以return new_node;
  • 短版:你的推送函数中的nstack = new_node;对调用者来说毫无意义。你所改变的只是一个局部变量,而不是调用者的指针。要么利用函数的其他未使用结果来返回新的指针值,要么按地址传递调用者的指针(作为指向指针的指针)并通过取消引用对其进行修改。此问题的 许多 个重复项之一can be found here

标签: c pointers linked-list stack


【解决方案1】:

因为您正在传递指针的副本(按值)。你需要这样的东西(指向指针的指针):

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct list_node {
    int element;
    struct list_node * pnext;
};

void push(struct list_node **operators, int e);

int pop(struct list_node *operators);


int main(int argc, char *argv[]) {
    //int newvalue = (int)argv[1][0];
    int newvalue = 1;
    struct list_node * nstack = (struct list_node*)malloc(sizeof(struct list_node));

    nstack->element = newvalue;
    nstack->pnext = NULL;

    int i;
        for (i = 2; i < 7; i++) {
            //push(nstack, (int)argv[i][0]);
            push(&nstack, i);
        }
    printf("top: %d\n", nstack->element);
}

void push(struct list_node **nstack, int e) {
    struct list_node * new_node = (struct list_node*)malloc(sizeof(struct list_node));
    new_node->pnext = *nstack;
    new_node->element = e;
    *nstack = new_node;
}

【讨论】:

    【解决方案2】:

    扩展 Tarod 的正确观点。调用者函数正在做的是获取指针值的副本并将其放入堆栈或寄存器(取决于编译器)中,然后将在您的推送函数中使用。但是,在您的 push 函数中,您实际上是在返回之前更改了此寄存器或堆栈位置中的值。但是,当您返回调用者函数时,基本上会丢弃此信息(它从堆栈中弹出 - 或者,再次取决于编译器,将寄存器用于其他用途)。解决这个问题的唯一方法是传递指针的地址,并在需要写入时遵循它,如 Tarod 所示。

    【讨论】:

    • 谢谢。我很欣赏你的评论。你有我的支持:)
    猜你喜欢
    • 2019-10-19
    • 2016-01-08
    • 2015-07-14
    • 1970-01-01
    • 2019-06-12
    • 2017-04-17
    • 1970-01-01
    • 2012-10-26
    • 1970-01-01
    相关资源
    最近更新 更多