在不使用malloc

时间:2019-05-03 20:08:22

标签: c

我在网上看到的所有实现都使用指针声明节点,然后将使用malloc为它们创建空间,如下所示:

struct Node  
{ 
  int data; 
  struct Node *next; 
}; 

int main() 
{ 
  struct Node* head = NULL; 
  struct Node* second = NULL; 
  struct Node* third = NULL; 

  head = (struct Node*)malloc(sizeof(struct Node));  
  second = (struct Node*)malloc(sizeof(struct Node)); 
  third = (struct Node*)malloc(sizeof(struct Node));
...

但是我也可以这样创建没有指针和malloc的对象:

struct node {
   int  id;
   struct node* next;
};

struct node head = {0, NULL};
struct node one = {1, NULL};
struct node two = {2, NULL};
struct node tail = {3, NULL};

int main(){
   head.next = &one;
   one.next = &two;
   two.next = &tail;
...

我的问题是,为什么第一种方法大部分是使用的,为什么我们需要将每个节点声明为指针,为什么需要malloc? (只需指出,我知道为什么将struct Node *next;声明为结构声明中的指针)。

2 个答案:

答案 0 :(得分:3)

您应该使用局部变量而不是全局变量来执行此操作,但是总体思路是相同的。您还应引导使用数组,而不要堆放其他不相关的变量:

struct node {
   int  id;
   struct node* next;
};

int main(){
  struct node nodes[4];

  for (int i = 0; i < 4; ++i) {
    nodes[i].id = (3 - i);

    if (i != 0) {
      nodes[i].next = &nodes[i-1];
    }
  }

  return 0;
}

为了方便起见,类似的东西以相反的顺序将它们组装在一起,但是最初它们在内存方面都归为一类。 使用

malloc是因为您通常不知道将要拥有多少,或者它们会意外地添加和删除。通用解决方案将根据需要分配它们。专门的实现可能会将它们分配为一个块,但这是高度情况。

这里nodes的寿命仅在该函数内,因此该函数结束后,数据就会消失。换句话说:

struct node* allocateNodes() {
  struct node nodes[10];

  return &nodes; // Returns a pointer to an out-of-scope variable, undefined behaviour
}

那行不通。您需要更长寿命的分配,这正是malloc提供的分配:

struct node* allocateNodes() {
  struct node *nodes = calloc(10, sizeof(struct node));

  return nodes; // Returns a pointer to an allocated structure, which is fine
}

问题是,如果您malloc负责调用free来释放内存,那么它将变得更多工作。

您将看到代码中使用的两种样式,这取决于所讨论变量的必需寿命。

答案 1 :(得分:3)

如果您提前知道列表中将有多少项,那么最好使用数组而不是列表。链表的全部要点是能够在运行时增长到未知大小,并且这需要动态内存分配(即malloc)。