u123
u123

Reputation: 16329

malloc and pointer in a struct

I have the following C code:

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;
}

I have a few problems:

  1. does DListNode * new_element = (DListNode *)malloc(sizeof(DListNode)); also allocate space for the, data, prev, next pointer or do I manually need to call malloc on each of those pointers?
  2. When I print the content of the data pointer in each node they all have the value 3 even though I insert 23, 7 and 11 and set the data pointer to the address of the int: ** new_element->data = &data;**.

(Introductionary textbooks on C have been ordered)

EDIT:

insert now takes a void pointer to the data:

// 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");
    }
}

In main I do:

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;
}

which outputs:

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

but it should be:

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

Upvotes: 3

Views: 2501

Answers (2)

Fred Foo
Fred Foo

Reputation: 363818

  1. malloc(sizeof(DListNode)) allocates space for exactly one DListNode, which by definition consists of a void* and two DListNode pointers. It does not initialize those pointers, though.

  2. You're assigning the address of the data argument to insert. That's a pointer to a temporary which is invalidated once insert returns. The behavior of the program is undefined. The easy solution is to just replace void *data by int data.

Upvotes: 3

KrisSodroski
KrisSodroski

Reputation: 2852

  1. You need to manually set those pointers to where they point with malloc. Without it, they will point to a space that isn't of size DListNode.

  2. Don't make the data a pointer. Just make the data an int (it gets auto allocated) and then just set data = data (the data that is passed into insert).

Upvotes: 0

Related Questions