2013-05-14 91 views
2

我有以下的C代码:malloc和指针

typedef struct DListNode_ { 
    void *data; 
    struct DListNode_ *prev; 
    struct DListNode_ *next; 
} DListNode; 


typedef struct DList_ { 
    int size; 
    DListNode *tail; 
    DListNode *head; 
} DList; 

void insert(DList * list, DListNode * element, int data) { 
    DListNode * new_element = (DListNode *)malloc(sizeof(DListNode)); 
    new_element->data = &data; 
    if (list->head==NULL) { 
     list->head=list->tail=new_element; 
     list->size++; 
     return; 
    } 
    if(element == NULL) { 
     // handle size==0? 
     new_element->next=list->head; 
     list->head->prev=new_element; 
     list->head=new_element; 
     list->size++; 
    } else { 
     printf("Not yet implemented!\n"); 
    } 
} 

void printNodes(DList *list) { 
    DListNode * pointer = list->head; 
    if (pointer!=NULL) { 
     int v= *((int*)pointer->data); 
     printf("Node has value: %d\n", v); 
     while (pointer->next != NULL) { 
      v = *((int*)pointer->data); 
      printf("Node has value: %d\n", v); 
      pointer=pointer->next; 
     } 
    } 
} 

int main(int argc, const char * argv[]) 
{ 

    int e0 = 23; 
    int e1 = 7; 
    int e2 = 11; 
    DList *list = (DList *)malloc(sizeof(DList)); 
    initList(list); 
    assert(count(list)==0); 
    insert(list, NULL, e0); 
    assert(count(list)==1); 

    insert(list,NULL, e1); 
    assert(count(list)==2); 

    insert(list,NULL, e2); 
    assert(count(list)==3); 
    printNodes(list); 

    return 0; 
} 

我有几个问题:

  1. 确实DListNode * new_element =(DListNode *)malloc的(的sizeof(DListNode ));也为数据,prev,next指针分配空间,还是我手动需要在每个指针上调用malloc?
  2. 当我在每个节点中打印数据指针的内容时,即使插入23,7和11并将数据指针设置为int的地址,它们也都具有值 **:new_element-> data = &data; **。

(基于C Introductionary教科书已订购)

编辑:

插入现在需要一个空指针数据:

// Insert data as the new head 
void insert(DList *list, DListNode *element, void *data) { 
    DListNode *new_element = malloc(sizeof(DListNode)); 
    new_element->data = data; 
    if (list->head==NULL) { 
     list->head=list->tail=new_element; 
     list->size++; 
     return; 
    } 
    if(element == NULL) { 
     new_element->next=list->head; 
     list->head->prev=new_element; 
     list->head=new_element; 
     list->size++; 
    } else { 
     printf("Not yet implemented!\n"); 
    } 
} 

在主要我做的:

int main(int argc, const char * argv[]) 
{ 
    int i0=7; 
    int *ip0 = malloc(sizeof(int)); 
    ip0 = &i0; 

    int i1=8; 
    int *ip1 = malloc(sizeof(int)); 
    ip1 = &i1; 

    int *ip2 = malloc(sizeof(int)); 
    int i2=44; 
    ip2 = &i2; 

    DList *list = malloc(sizeof(DList)); 
    initList(list); 
    // create some nodes 
    assert(count(list)==0); 
    insert(list, NULL, ip0); 
    assert(count(list)==1); 

    insert(list,NULL, ip1); 
    assert(count(list)==2); 

    insert(list,NULL, ip2); 
    assert(count(list)==3); 
    printNodes(list); 

    return 0; 
} 

其中输出:

Node has value: 44 
Node has value: 44 
Node has value: 8 

,但它应该是:

Node has value: 44 
Node has value: 8 
Node has value: 7 
+4

您不需要在C程序中投射'malloc'的返回值。 – 2013-05-14 18:21:21

+0

“DListNode_”只不过是其字段的总和。除了你提到的指针之外,没有什么可以分配的。 – ApproachingDarknessFish 2013-05-14 18:25:21

回答

0
  1. 您需要手动设置这些指针,它们指向使用malloc哪里。没有它,他们会指向一个不是DListNode大小的空间。

  2. 不要将数据作为指针。只需将数据设置为int(它会自动分配),然后设置data = data(传入insert的数据)。

+0

'malloc'可能*不是正常列表语义所必需的。只需将它们指向预先存在的节点(如果没有任何节点,则指向NULL)。 – 2013-05-14 18:23:22

+1

是的,只要在那里已经有一个节点,你是对的。否则,当你创建一个节点时,最简单的方法就是将这些结构从下一个指针中分配出来。 – Magn3s1um 2013-05-14 18:24:18

+0

为什么你会这样做?如果你还没有一个节点,你希望列表指针都是NULL,对吧? – 2013-05-14 18:24:32

3
  1. malloc(sizeof(DListNode))恰好一个DListNode,根据定义由void*和两个DListNode指针的分配空间。不过,它并不初始化这些指针。

  2. 你分配data参数的地址insert。这是一个临时指针,一旦insert返回就会失效。程序的行为是未定义的。简单的解决方案是用int data代替void *data

+1

..并初始化它们可能不需要调用'malloc'。事实上,对于正常的链表行为,你可能*不会*'malloc'它们。 – 2013-05-14 18:23:59

+0

@CarlNorum:我不确定你的意思。每当(或者:几次)我用C实现链表时,我会''malloc''每个节点分开,尽管这在每种情况下都不需要。 – 2013-05-14 18:27:28

+0

我很确定(虽然他可以纠正我,如果我错了)OP询问他是否需要在他的程序的当前调用之后再次调用malloc三次以初始化列表结构中的指针。我只是说他可能没有。 – 2013-05-14 18:28:16