I'm quite newbie in C and now I'm trying to implement basic generic linked list with 3 elements, each element will contain a different datatype value — int, char and double.
Here is my code:
#include <stdio.h>
#include <stdlib.h>
struct node
{
void* data;
struct node* next;
};
struct node* BuildOneTwoThree()
{
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));
head->data = (int*)malloc(sizeof(int));
(int*)(head->data) = 2;
head->next = second;
second->data = (char*)malloc(sizeof(char));
(char*)second->data = 'b';
second->next = third;
third->data = (double*)malloc(sizeof(double));
(double*)third->data = 5.6;
third->next = NULL;
return head;
}
int main(void)
{
struct node* lst = BuildOneTwoThree();
printf("%d\n", lst->data);
printf("%c\n", lst->next->data);
printf("%.2f\n", lst->next->next->data);
return 0;
}
I have no problem with the first two elements, but when I try to assign a value of type double to the third element I get an error:
can not convert from double to double *
My questions:
What is the reason for this error?
Why don't I get the same error in case of int or char?
How to assign a double value to the data field of the third element?
The problem string is (double*)third->data = 5.6;.
In your "working" examples, you're calling malloc to get a pointer to some newly-allocated space, and then immediately throwing that pointer away and replacing the pointer value with your integer or character value. That works more or less by accident because in most C implementations a pointer cell can hold an integer or char value, though you should be getting warnings. If you actually tried to dereference the data pointer after those assignments, you would probably get a crash and core dump.
You want to put the values at the place pointed to by the pointer, not in the pointer itself. Which means you need an extra *:
*((double *)third->data) = 5.6;
The * in the (double *) typecast is part of the type name - "pointer to double". The cast says "take the value of third->data and interpret it as a pointer to double". The result is still a pointer, so when you assign to that, you are changing where the pointer points (and probably making it point somewhere meaningless). Instead, you want to assign a value to the place it already points, which is what the outer * does.
However, if you're only storing basic types like int, char, and double, you don't need to go through a pointer (and worry about the attendant memory management). You can just use a union:
struct node
{
struct node *next;
union {
char c;
int i;
double d;
} data;
}
Then you would do e.g.
head->data.i = 2;
second->data.c = 'b';
third->data.d = 5.6;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With