在c中堆积分配

时间:2015-11-29 08:46:58

标签: c

#include <stdio.h>
#include <malloc.h>
typedef struct Node {
    int value;      //4
    struct Node* next;      //4
}Node;
Node *create();
void add();
void del();
void search();

Node *create(int v) {
     Node *first;
     first = (Node *)(calloc(1,sizeof(*first)));
     first->value = v;
     first->next = NULL;
     return first;
}
void add(Node **head,int v) {
    Node *p;
    p = (Node *)(calloc(1,sizeof(*p)));
    p->value = v;
    p->next = *head;
    *head = p;

 }
void search(Node *head) {
    Node *p;
    p=head;
    while(p != NULL) {
        printf("address is %d;value address is %d;next address is %d;next content is %d\n",p,&(p->value),&(p->next),p->next);
        p = p->next;
   }
}



int main() {
     Node *head;
     head = create(0);
     add(&head,1);
     add(&head,2);
     add(&head,3);
     search(head);
}

enter image description here

sizeof(Node) == 8,但为什么堆中每个节点的大小都是16个字节?想 (我的系统是32位)。 struct node是4bytes + 4bytes = 8bytes。

4 个答案:

答案 0 :(得分:2)

节点大小不是16个字节,只是malloc()选择跳过8个字节的内存由于某种原因,可能是它自己的簿记。如果你想节省内存,做一些大的分配,而不是很少的小分配,否则簿记费用可能会花费很多。

答案 1 :(得分:1)

好吧,即使在calloc()的来电之间分配的内存对你的程序来说是连续的(你无法确定),也不要忘记lib c有私有的&#39;存储在您分配的内存块中的数据。

通常会有一个标题:

struct hdr
{
  size_t size;                  /* Exact size requested by user.  */
  unsigned long int magic;      /* Magic number to check header integrity.  */
  struct hdr *prev;
  struct hdr *next;
  __ptr_t block;                /* Real block allocated, for memalign.  */
  unsigned long int magic2;     /* Extra, keeps us doubleword aligned.  */
};

code from

您可能会看到该块实际上是您在调用malloc() / calloc()时获得的数据缓冲区,其中包含大量额外数据( ok,这里是调试的特例,因此可能有额外的魔法)。

答案 2 :(得分:0)

代码中涉及的错误是与各种列表函数相关的逻辑错误。当您具有add函数时,该函数的作用是为节点分配内存并分配所需的任何值。它不担心它正在处理哪个节点。

相反,你的create函数没有分配任何东西,它只是调用add来处理那项工作,然后它的工作只是正确地连接指针和next-&gt;指向正确节点的指针。 / p>

由于您正在处理包含数据的头节点,因此head有3种可能的条件; (1)当NULLhead->next时; (2)当NULL#include <stdio.h> #include <stdlib.h> typedef struct Node { int value; //4 struct Node* next; //4 } Node; /* function prototypes */ Node *create (int v); void add (Node **head, int v); void del (); void search (Node *head); void printvalues (Node *head); int main (void) { Node *head = NULL; // head = create(0); add (&head,0); add (&head,1); add (&head,2); add (&head,3); printf ("\nsearching:\n\n"); search (head); printf ("\nprinting:\n\n"); printvalues (head); return 0; } /* create - only creates nodes */ Node *create (int v) { Node *new; new = calloc (1, sizeof *new); new->value = v; new->next = NULL; return new; } /* add does NOT create - only handles wiring */ void add (Node **head, int v) { Node *new = create (v); if (!*head) { *head = new; return; } Node *p = *head; while (p && p->next) p = p->next; if (!(*head)->next) (*head)->next = new; else p->next = new; } void search(Node *head) { Node *p = head; while (p != NULL) { printf (" address is %p; next address is %p;\n", p, p->next); p = p->next; } } void printvalues (Node *head) { Node *p = head; unsigned cnt = 0; while (p != NULL) { printf (" node[%2u] value: %d\n", cnt++, p->value); p = p->next; } } 时; (3)所有剩余的补充。

将这些部分组合在一起并添加打印功能,您的代码可能如下所示:

$ ./bin/dbgllmess

searching:

  address is 0x1acf010;  next address is 0x1acf030;
  address is 0x1acf030;  next address is 0x1acf050;
  address is 0x1acf050;  next address is 0x1acf070;
  address is 0x1acf070;  next address is (nil);

printing:

  node[ 0] value: 0
  node[ 1] value: 1
  node[ 2] value: 2
  node[ 3] value: 3

<强>输出

{{1}}

注意:您负责释放不再需要的内存。如果您有任何问题,请告诉我。

答案 3 :(得分:0)

关于真正的问题“为什么堆中每个节点的大小都是16个字节?”

好吧,你不能指望一个内存块正好位于前一个内存块所在的末尾。你不能假设任何关于堆如何被密切管理的事情。即使用malloc全部涂层,两块也可以相互保持千兆字节的距离。

在Windows上,为了使堆能够跟踪分配的内存块,每个块都会获得更多的字节来保存内存块的元数据。这被称为“堆条目”,这可能是你的块更大的原因。

但同样,你不能假设任何块 - 无论如何都要在堆中定位。