user1427661
user1427661

Reputation: 11774

Struct Pointers on a Linked List Implementation

I'm working on a linked list implementation in C to get the hang of pointers and structs. Here is the basic code for my LL data structure:

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

struct List {
    struct Node *head;
};

void initList(struct List *list) {
    list->head = 0;
}

struct Node *addFront(struct List *list, void *data) {
    struct Node *newNode;
    newNode->data = data;
    newNode->next = list->head;
    list->head = newNode;
    return newNode;
}

Here is the test I run on it in the int main() function:

int main() {
    /* test addFront */
    double *data1;
    double *data2;
    *data1 = 10.5;
    *data2 = 10.7;
    struct List *newList;
    initList(newList);
    addFront(newList, data1);
    printf("%s\n", newList->head->data);
    addFront(newList, data2);
    printf("%s\n", newList->head->data);

    return 0;
}

My problem is that printf is not printing the output. As it stands now, it obviously doesn't print because %s doesn't match the data type, which is double. If I change the string format to %d, it gives me a segmentation fault. If I add a (double) cast, it says that the second argument has type double *, which confuses me because I thought the -> notation dereferenced a pointer.

I'm lost.

Upvotes: 2

Views: 4334

Answers (4)

Dmytro
Dmytro

Reputation: 5213

What have you done to try to deal with the problem?

try using "assert.h" to ensure your assertions are right, or if statements with puts/exit.

In particular, if it doesn't print something, clearly what your are printing is not what you want to print, so somewhere along the lines, an assertion must fail, and your mind will "click" where you missed a step.

The reason I can't do this immediatly is because I am not you and I do not know what assertions you are making, so it will take me longer to place them than you would.

Also, as pointed above, you are not allocating memory for newNode, and accessing arbitrary memory, which is causing segmentation fault.

There I fixed it.

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>

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

struct List {
    struct Node *head;
};

void initList(struct List **newList)
{
    struct List* tmpList = 0;

    assert(newList != 0);
    tmpList = (struct List*)malloc(sizeof(struct List*));
    assert(tmpList != 0);
    tmpList->head = 0;
    *newList = tmpList;
}

void addFront(struct List* list, void* data)
{
    struct Node* currNode = 0;
    struct Node* prevNode = 0;

    assert(list != 0);
    assert(data != 0);

    currNode = list->head;
    while (currNode != 0) {
        prevNode = currNode;        
        currNode = currNode->next;
    }
    if (prevNode == 0) {
        list->head = (struct Node*)malloc(sizeof(struct Node));
        list->head->data = data;
        list->head->next = 0;
    } else {
        prevNode->next = (struct Node*)malloc(sizeof(struct Node));
        prevNode->next->data = data;
        prevNode->next->next = 0;
    }
}

void test(const struct List *list)
{
    const struct Node *iter;
    assert(list != 0);
    assert(list->head != 0);
    iter = list->head;

    while (iter != 0) {
        assert(iter->data != 0);
        printf("%f\n", *((double*)iter->data));
        iter = iter->next;
    }   
}

int main()
{
    double* data1 = (double*)malloc(sizeof(double));
    double* data2 = (double*)malloc(sizeof(double));
    *data1 = 10.5;
    *data2 = 10.7;
    struct List* newList = 0;

    initList(&newList);
    assert(newList->head == 0);
    puts("pass[0].");

    addFront(newList, data1);
    assert(newList->head != 0);
    assert(newList->head->data == data1);
    puts("pass[1].");

    addFront(newList, data2);
    assert(newList->head != 0);
    assert(newList->head->data == data1);
    assert(newList->head->next != 0);
    assert(newList->head->next->data == data2);
    puts("pass[2].");

    test(newList);

    return 0;
}

Upvotes: 1

David W
David W

Reputation: 10184

You are not allocating memory for your double pointers data1 and data2.

Looks like, actually, you're not allocating memory for nearly any of your pointers.

All a pointer does by itself is reference an address in memory. It does not allocate the memory necessary to support the referenced structure or variable.

If you have

double *data1; // or any other kind of pointer

you need something like

data1 = (double *) malloc(sizeof(double));

THEN you can dereference all you like, eg

*data1 = 12.34;

But without that, your referencing a pointer to the Black Hole of Calcutta.

Upvotes: 3

Bernd Elkemann
Bernd Elkemann

Reputation: 23550

In addition to the 2 printf("%f") there are 4 malloc's missing:

I marked the changed lines with ###:

#include "stdlib.h"
#include "stdio.h"
struct Node {
    void *data;
    struct Node *next;
};

struct List {
    struct Node *head;
};

void initList(struct List *list) {
    list->head = 0;
}

struct Node *addFront(struct List *list, void *data) {
    struct Node *newNode = malloc(sizeof(struct Node)); //###
    newNode->data = data;
    newNode->next = list->head;
    list->head = newNode;
    return newNode;
}
int main() {
    /* test addFront */
    double *data1 = malloc(sizeof(double)); //###
    double *data2 = malloc(sizeof(double)); //###
    *data1 = 10.5;
    *data2 = 10.7;
    struct List *newList = malloc(sizeof(struct List)); //###
    initList(newList);
    addFront(newList, data1);
    printf("%f\n", *(double*)newList->head->data);//###
    addFront(newList, data2);
    printf("%f\n", *(double*)newList->head->data);//###
    // TODO: free()'s //###
    return 0;
}

Upvotes: 1

cnicutar
cnicutar

Reputation: 182609

You are dereferencing data1 and data2 without assigning memory to them. Try:

double data1 = 10.5;

addFront(newList, &data1);

Alternatively you could do a malloc, although I don't think you should in this case.

Also, when you want to print them, try:

printf("%f\n", *(double *)newList->head->data);

Upvotes: 3

Related Questions