C链表循环引用



所以我对C很陌生,但对编程不熟悉。我正在尝试学习C,所以我决定尝试实现一个简单的链表。

这是代码:

#include <stdio.h>
typedef struct node node;
struct node {
    char *word;
    node *next;
};
// Returns a node.
node node_new(char *word) {
    node n;
    n.word = word;
    n.next = NULL;
    return n;
}
// Traverses the linked list, spitting out the
// words onto the console.
void traverse(node *head) {
    node *cur = head;
    while (cur != NULL) {
        printf("I have %s.n", cur->word);
        cur = cur->next;
    }
    printf("Done.n");
    return;
}
// In here I get circular references whenever I pass a second argument.
void dynamic(int argc, char **argv) {
    printf("DYNAMIC:n");
    node n = node_new("ROOT");
    node *cur = &n;
    int i;
    for (i = 0; i < argc; i++) {
        node next = node_new(argv[i]);
        cur->next = &next;
        cur = &next;
    }
    traverse(&n);
}
void predefined(void) {
    printf("PREDEFINED:n");
    node n = node_new("ROOT");
    node a = node_new("A");
    node b = node_new("B");
    node c = node_new("C");
    n.next = &a;
    a.next = &b;
    b.next = &c;
    traverse(&n);
}
int main(int argc, char **argv) {
    predefined();
    dynamic(argc, argv);
    return 0;
}

如果我只是在没有参数("./test")的情况下运行它,输出是:

PREDEFINED:
I have ROOT.
I have A.
I have B.
I have C.
Done.
DYNAMIC:
I have ROOT.
I have ./test.
Done.

但如果我加上任何参数,而不是"我有./test",它会给出一个无限循环,无论命令行上最后一个参数是什么("./test one two three"给出"我有三个"。一遍又一遍地忽略"一"one_answers"二",但前面的行是一样的)。

我认为这与动态函数中糟糕的指针管理有关,但我不明白为什么它要将自己设置为自己的"下一个"节点。

问题就在这里:

for (i = 0; i < argc; i++) {
    node next = node_new(argv[i]);
    cur->next = &next;
    cur = &next;
}

通过像这样分配next,它仍然与堆栈绑定,并且在每次迭代中实际上不会更改地址。每次都应该是一个新对象:

for (i = 0; i < argc; i++) {
    node *next = malloc (sizeof node);
    next->word = argv[i];
    next->next = NULL;
    cur->next = next;
    cur = next;
}

此外,node_new()也不能使用,因为它也没有分配任何持久的新内存。

问题出在for循环中。每次迭代都使用堆栈上相同的内存位置来存储next变量。因此,实际上,&next给出的内存位置对于整个for循环来说是一个常数,当您运行traverse时,该内存位置包含next的最后一个值。

你的for循环相当于这个版本,它可能会提供更多的线索:

int i;
node next;  // note this line
for (i = 0; i < argc; i++) {
    next = node_new(argv[i]);
    cur->next = &next;
    cur = &next;
}

如果您希望能够传递它们的地址,或者将它们的地址存储在其他数据结构中,则需要在堆上创建新节点。阅读mallocfree

相关内容

  • 没有找到相关文章

最新更新