C - 堆栈分配的链表

时间:2017-07-18 22:33:50

标签: c linked-list

我使用以下代码的目标是让用户输入一些整数,将这些整数存储在堆栈分配的类型为INT_NODE的节点中,然后将所有这些节点链接在一起。最后,我想遍历列表并在每个节点打印出元素(只有以下代码中的前5个)。但是,当我输入一些数字时,程序会输出我输入的第一个数字,然后输入的最后一个数字重复4次。例如,如果我输入84 5 12 7 1 22 31[Enter]然后在下一行的开头按Ctrl+D来模拟此Mac上的EOF,我会得到以下输出; 84 31 31 31 31。我无法弄清楚它为什么会这样做。

我知道我可以使用malloc()在堆上分配节点,并且我已经编写了一个函数来执行此操作。我只是想知道是否可以使用运行时堆栈来完成它。

在以下代码中,INT_NODE标题在"SortingAlgs.h"标题中定义如下;

typedef struct INT_NODE {
    int element;
    struct INT_NODE *next;
} INT_NODE;
#include <stdio.h>
#include <stdlib.h>
#include "SortingAlgs.h"

int main(void) {

    INT_NODE head = {-999999999};
    int num;
    INT_NODE *pCurrentNode = &head;

    if (scanf("%d", &num) != EOF) {
        head.element = num;

        while (scanf("%d", &num) != EOF) {
            INT_NODE newNode;

            newNode.element = num;
            newNode.next = NULL;
            pCurrentNode->next = &newNode;
            pCurrentNode = pCurrentNode->next;
        }
    } 
    int i;
    for (pCurrentNode = &head, i = 0; i < 5;
         pCurrentNode = pCurrentNode->next, i++)

        printf("%d  ", pCurrentNode->element);

    printf("\n");

    return 0; 
}

2 个答案:

答案 0 :(得分:4)

要使用运行时堆栈执行此操作,您可以使用以下方法之一:

  1. 通过alloca进行运行时分配。这很简单:基本上只需将malloc替换为alloca(并且不要尝试将alloca包装到另一个函数中)。但是,alloca不是标准函数。
  2. 递归函数,其中每个递归级别将承载单个列表节点(或固定数量的列表节点)。这有一些严重的限制,但从技术上讲,它符合您在堆栈上分配所有节点的要求。
  3. 预先分配固定数量的节点作为本地阵列,并希望它对您的列表足够......但我确定这不是您的意思。
  4. 关于它。你现在拥有的是不可行的,只会导致未定义的行为。你的清单基本上是&#34;包括&#34;生命周期已经结束的INT_NODE个对象在实践中,您通常会一次又一次地重复使用相同的内存位置,从而有效地将单个节点链接到自身。

    这是一个示例,如果一个实现将整个列表保留在堆栈上#34;遵循递归方法。当然,只要所有递归调用都是&#34;活动&#34;,该列表就存在。这限制了这种技术的适用性,但它使用了

    #include <stdlib.h>
    #include <stdio.h>
    
    typedef struct INT_NODE 
    {
      int element;
      struct INT_NODE *next;
    } INT_NODE;
    
    void print_list(const INT_NODE *head)
    {
      for (const INT_NODE *current = head; current != NULL; current = current->next)
        printf("%d  ", current->element);
      printf("\n");
    }
    
    void build_list(INT_NODE *head, INT_NODE *last)
    {
      INT_NODE new = { 0 };
    
      if (scanf("%d", &new.element) != 1)
      {
        print_list(head);
        return;
      }
    
      if (head == NULL)
        head = &new;
      else
        last->next = &new;
    
      build_list(head, &new);
    }
    
    int main(void) 
    {
      build_list(NULL, NULL);
    }
    

    http://coliru.stacked-crooked.com/a/5a4f15a82c66d992

答案 1 :(得分:1)

我认为原因是变量的范围。 输入5,程序在堆栈上分配内存,但会返回。 输入12,分配相同的内存,返回它。 所以最后,头部下一个指针是相同的内存,并且相同的内存下一个指针本身。

你可以输出超过5.也许你会得到84 31 31 31 31 31 31 31 .....