i have a dynamic number of pointers all having the same size. i need to store all the addresses of my pointers in some place like a link List in order to fetch them later on.
my question is what structs should i use. is the following correct:
struct Node{
int *k;
Node*Next;
}
struct LS{
Node*first,*last;
void push(Node*n);
Node* GetFirst();
Node* GetLast();
}
the LS is the linked list that stores Nodes. and a Node is a struct that holds the address of my pointer and a pointer to the next Node.
am i using int *k to store the address of my pointer correctly? should i continue with this implementation or is there any easier way to do this?
this sample code may help you start...
#include <stdio.h>
struct Node{
int *k;
Node *Next;
}* Temp;
struct LS
{
Node *first,*last;
void push(Node *MyNode)
{
MyNode->Next=NULL;
if(empty())
{
first=MyNode;
last=MyNode;
}
else
{
last->Next = MyNode;
last=MyNode;
}
}
Node* front()
{
return first;
}
void pop()
{
free(first->k);
first=first->Next;
}
bool empty()
{
if(first==NULL) return true;
return false;
}
};
int N=10;
int main()
{
LS Q;Q.first=NULL;
for(int i=0;i<3;i++)
{
Node *NewNode= (Node*)malloc(sizeof(Node));
NewNode->k = (int*)malloc(sizeof(int)*N);
for(int k=0;k<N;k++) NewNode->k[k]=i;
Q.push(NewNode);
}
while(!Q.empty())
{
Temp=Q.front();
for(int i=0;i<N;i++) printf("%d ",Temp->k[i]);
printf("\n");
Q.pop();
}
return 1;
}
Yes, your Node struct is correct.
As to whether there is an easier way it depends. If there is a maximum number of pointers that you will need then an array of pointers would be easier. If you can do it in C++ then an STL vector (can use it like an array, but underneath the hood it can grow dynamically as needed) is easier. If you have to do it in C and it has to be dynamic, though, then no, there is not an easier way.
WDM.H (microsoft header) has a bunch of linked list stuff to look at ( http://msdn.microsoft.com/en-us/library/ff547799(VS.85).aspx ) , I've cut and pasted from that, and added a very simple example.
typedef struct _LIST_ENTRY {
struct _LIST_ENTRY *Flink;
struct _LIST_ENTRY *Blink;
} LIST_ENTRY, *PLIST_ENTRY;
typedef struct _MY_THING
{
LIST_ENTRY ListEntry;
ULONG randomdata1;
ULONG randomdata2;
ULONG randomdata3;
ULONG randomdata4;
} MY_THING, *PMY_THING;
#define CONTAINING_RECORD(address, type, field) ((type *)( \
(PCHAR)(address) - \
(ULONG_PTR)(&((type *)0)->field)))
VOID
InsertHeadList(
IN PLIST_ENTRY ListHead,
IN PLIST_ENTRY Entry
)
{
PLIST_ENTRY Flink;
Flink = ListHead->Flink;
Entry->Flink = Flink;
Entry->Blink = ListHead;
Flink->Blink = Entry;
ListHead->Flink = Entry;
}
VOID
InitializeListHead(
IN PLIST_ENTRY ListHead
)
{
ListHead->Flink = ListHead->Blink = ListHead;
}
PLIST_ENTRY
RemoveHeadList(
IN PLIST_ENTRY ListHead
)
{
PLIST_ENTRY Flink;
PLIST_ENTRY Entry;
Entry = ListHead->Flink;
Flink = Entry->Flink;
ListHead->Flink = Flink;
Flink->Blink = ListHead;
return Entry;
}
void main()
{
LIST_ENTRY HeadOfMyList;
MY_THING Thing;
InitializeListHead(&Head);
// example of add thing to list.
InsertHeadList(&HeadOfMyList, &Thing.ListEntry);
// example of removing thing from the list
PLIST_ENTRY listEntry = RemoveHeadList(&HeadOfMyList);
PMY_THING pThing = (PMY_THING) CONTAINING_RECORD(listEntry, MY_THING, ListEntry);
}
Related
Suppose I have two structures in my code like this:
typedef struct Food {
char* name;
int food_id;
int price;
int capacity;
int hall_id;
int day;
int reserved;
int profit;
Food* next;
} Food;
typedef struct Coupon {
int id;
int percentage;
int capacity;
Coupon* next;
} Coupon;
And I want to implement a linked list data structure with them. For example I have a Food* variable which points to food number 1 and then food number 2 in next points to the next food and...
The problem is when I want to write functions for the linked lists, I have to write 2 functions for every job. For example I want to have a function that gets the head of the list and a new element, then add the new element to the list. Because the types of these two linked lists are different, I can't think of a way to write only one function for both. Is there a way to do so?
For example I want to make this function work for all types:
void add_front(Coupon* head, Coupon* new_el){
while (head->next != NULL){
head = head->next;
}
head->next = new_el;
new_el->next = NULL;
}
First, you separate the domain data of each entry from the managing data.
typedef struct {
char* name;
int food_id;
int price;
int capacity;
int hall_id;
int day;
int reserved;
int profit;
} Food;
typedef struct {
int id;
int percentage;
int capacity;
} Coupon;
Then you can use a union with pointers to the domain data in the entry's structure. Each entry will be of the same size.
typedef struct Entry {
struct Entry* next;
union {
Food* food;
Coupon* coupon;
} data;
} Entry;
You could even place the domain data directly in the union, but this will waste memory if only small sized values are stored.
typedef struct Entry {
struct Entry* next;
union {
Food food;
Coupon coupon;
} data;
} Entry;
Now you are able to add new entries of different data with a generic function.
void add_front(Entry* head, Entry* new_el) {
while (head->next != NULL){
head = head->next;
}
head->next = new_el;
new_el->next = NULL;
}
A possible trick is to use the fact that it is legal to convert a pointer to a struct to a pointer to its initial member, and that it is legal to convert from any pointer type to void * and back. So provided next is the first member, a number of functions could be independant of the actual class, if they take void * parameters for any struct for which the first element is a next pointer. Of course, auxiliary function able to handle a real object should be provided...
Here is an example code showing a possible implementation of add_before, add_after, list_remove (remove is defined in stdio.h) and display and showing an example of use with Coupon objects:
#include <stdio.h>
typedef struct Food {
struct Food* next;
char* name;
int food_id;
int price;
int capacity;
int hall_id;
int day;
int reserved;
int profit;
} Food;
typedef struct Coupon {
struct Coupon* next;
int id;
int percentage;
int capacity;
} Coupon;
void* add_before(void* list, void* elem) {
*(void **)elem = list;
return elem;
}
void* add_after(void* list, void* elem) {
if (NULL == list) return elem;
void** last = list;
while (*last != NULL) {
last = *last;
}
*last = elem;
return list;
}
// eltdisplay is a pointer to a function able to display an element
void display(void* list, void (*eltdisplay)(void*, FILE *), FILE *out) {
while (NULL != list) {
eltdisplay(list, out);
if (NULL != *(void **)list) {
fprintf(out, " -> ");
}
list = *(void **)list;
}
fprintf(out, "\n");
}
void* list_remove(void* list, void* elem, int(*comp)(void* elt1, void* elt2)) {
if (list == NULL) return NULL;
void** cur = list, **old = NULL;
while (cur != NULL) {
if (0 == comp(cur, elem)) {
if (old == NULL) return *cur;
*old = *cur;
break;
}
old = cur;
cur = *cur;
}
return list;
}
int couponcomp(void* elt1, void* elt2) {
return ((Coupon*)elt1)->id != ((Coupon*)elt2)->id;
}
void coupondisplay(void* elt, FILE *out) {
Coupon* coupon = elt;
fprintf(out, "%d", coupon->id);
}
int main() {
Coupon data[3] = { {NULL, 1}, {NULL, 2}, {NULL, 3} };
Coupon* list = NULL;
for (int i = 0; i < sizeof(data) / sizeof(*data); i++) {
list = addLast(list, data+i);
}
display(list, coupondisplay, stdout);
Coupon data2 = { NULL, 2 };
list = list_remove(list, &data2, couponcomp);
display(list, coupondisplay, stdout);
return 0;
}
It compiles with no warning and displays as expected:
1 -> 2 -> 3
1 -> 3
You could use a macro :
From one of my personal project
#if !defined(CIRCULAR_DOUBLE_LINKED_LIST_H)
#define CIRCULAR_DOUBLE_LINKED_LIST_H
//T must include ->prev and ->next member
#define DECLARE_NAMED_CIRCULAR_DOUBLE_LINKED_LIST(T, name) \
static inline T* name ## _add_after(T* source, T* item) { \
T* last_next = source->next; \
source->next = item; \
item->prev = source; \
item->next = last_next; \
last_next->prev = item; \
return source; \
} \
static inline T* name ## _add_before(T* source, T* item) {\
T* last_prev = source->prev; \
source->prev = item; \
item->next = source; \
item->prev = last_prev; \
last_prev->next = item; \
return source; \
} \
static inline T* name ## _remove(T* item) { \
T* next = item->next; \
item->prev->next = item->next; \
item->next->prev = item->prev; \
return next == item ? NULL : next; \
}
#define DECLARE_CIRCULAR_DOUBLE_LINKED_LIST(T) DECLARE_NAMED_CIRCULAR_DOUBLE_LINKED_LIST(T, list_ ## T)
#endif // CIRCULAR_DOUBLE_LINKED_LIST_H
typedef struct Food {
Food* next;
Food* prev;
char* name;
int food_id;
int price;
int capacity;
int hall_id;
int day;
int reserved;
int profit;
} Food;
DECLARE_CIRCULAR_DOUBLE_LINKED_LIST(Food)
list_Food_add_after(Food*, Food*);
list_Food_add_before(Food*, Food*);
list_Food_remove(Food*);
I think the best way I ever found to do this in C (i.e., without templates) was:
Make a SinglyLinkedNode class that just has SinglyLinkedNode *next
Write your list functions based on this class -- every list is a list of SinglyLinkedNode
Add SinglyLinkedNode node fields to Food and Coupon, and use that to link them together.
Additionally provide functions or macros to get the containing Food or Coupon pointer from a SinglyLinkedNode pointer, like Coupon *couponFromNode(Node *p);
Note that I would never actually do this for singly-linked lists, because singly-linked list operations are so easy to write that you don't really need list methods. This technique starts to get useful for doubly-linked lists or more complex introspective containers.
So I looked everywhere to get inspired but I didn't really find anything for rehashing a hash table using separate chaining method. So I tried myself, I think I know what I'm doing wrong, but I don't know how else to implement it, please help.
Everything works, except the new added function rehash()
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stddef.h>
struct list_node
{
struct list_node *next;
char *key;
char *value;
};
struct hash_table
{
int table_size;
struct list_node **list_arr;
};
unsigned int hash(const char *key, unsigned int table_size);
struct hash_table *initialize(unsigned int table_size);
struct list_node *find(struct hash_table *H, const char *key);
void insert(struct hash_table *H, const char *key, const char *value);
void dump(struct hash_table *H);
void del(struct hash_table *H, const char *key);
struct hash_table *rehash(struct hash_table *H);
unsigned int
hash(const char *key, unsigned int table_size)
{
unsigned long int hashx = 0;
for(int i=0;key[i];i++)
{
hashx = (hashx<<5) + key[i];
}
return (hashx%table_size);
}
struct hash_table
*initialize(unsigned int table_size)
{
struct hash_table *H = malloc(sizeof(*H));
H->list_arr = malloc(sizeof(*H->list_arr)*table_size);
H->table_size = table_size;
for(unsigned int i = 0; i<table_size; i++)
{
H->list_arr[i] = malloc(sizeof(*H->list_arr[i]));
H->list_arr[i]->next = NULL;
}
return H;
}
void
insert(struct hash_table *H, const char *key, const char *value)
{
unsigned int index = hash(key, H->table_size);
struct list_node *head = H->list_arr[index];
struct list_node *current = head->next;
while(current!=NULL)
{
if(strcmp(current->key,key)==0)
{
free(current->value);
current->value = malloc(strlen(value)+1);
strcpy(current->value,value);
return;
}
current=current->next;
}
struct list_node *newNode = malloc(sizeof(*H->list_arr[index]));
newNode->next = head->next;
head->next = newNode;
newNode->key = malloc(strlen(key)+1);
newNode->value = malloc(strlen(value)+1);
strcpy(newNode->key,key);
strcpy(newNode->value,value);
}
void
dump(struct hash_table *H)
{
for( int i = 0; i<H->table_size; i++)
{
struct list_node *entry = H->list_arr[i]->next;
if(entry==NULL){continue;}
printf("Index[%d]: ", i);
while(entry!=NULL)
{
printf("\t%s|%s\t--> ", entry->key, entry->value);
entry = entry->next;
}
printf("\tNULL");
printf("\n");
}
}
void delete(struct hash_table *H, const char *key)
{
unsigned int index = hash(key,H->table_size);
struct list_node *prev = H->list_arr[index];
while(strcmp(prev->next->key,key)!=0)
{
if(prev->next==NULL){printf("Key not found!");return;}
prev=prev->next;
}
struct list_node *temp = prev->next;
prev->next = temp->next;
free(temp);
}
struct hash_table *rehash(struct hash_table *H)
{
unsigned int old_size = H->table_size;
struct list_node *old_entries = H->list_arr;
H = initialize(2*old_size);
for(unsigned int i = 0; i<old_size; i++)
{
while(old_entries[i]!=NULL)
{
insert(H,old_entries[i].key,old_entries[i].value);
old_entries[i] = old_entries[i]->next;
}
}
free(old_entries);
return H;
}
int main()
{
struct hash_table *H = initialize(20);
insert(H,"name1","David");
insert(H,"name2","Radka");
dump(H);
H = rehash(H);
dump(H);
return 1;
}
I think doing old_entries[i] is wrong, but nothing else comes to mind, please help me resolve this.
OK! After thinking about it for a while, I realized I created a struct list_node pointer variable that points to H->list_arr which is an array of pointers. That was my mistake. I was supposed to declare it as a double pointer.
Here's the modified rehash() function:
struct hash_table *rehash(struct hash_table *H)
{
unsigned int old_size = H->table_size;
struct list_node **old_entries = H->list_arr;
H = initialize(2*old_size);
for(unsigned int i = 0; i<old_size; i++)
{
old_entries[i] = old_entries[i]->next;
while(old_entries[i]!=NULL)
{
insert(H,old_entries[i]->key,old_entries[i]->value);
old_entries[i] = old_entries[i]->next;
}
}
free(old_entries);
return H;
}
with this code, you will have to return the address of the new hash_table to the pointer pointing to the old hash_table --> [H = rehash(H)] since passing the pointer H as a parameter will only change it locally. Therefore, I tried a second version (because I'm too lazy;) and inattentive and might forget to reassign it) where I don't have to return anything, I want to change it simply by calling the function and my pointer points to the new hash_table automatically -> [rehash(&H)], here's the other "lazy" alternative:
void
rehash(struct hash_table **H)
{
unsigned int old_size = (*H)->table_size;
struct list_node **old_entries = (*H)->list_arr;
*H = initialize(2*old_size);
for(unsigned int i = 0; i<old_size; i++)
{
old_entries[i] = old_entries[i]->next;
while(old_entries[i]!=NULL)
{
insert(*H,old_entries[i]->key,old_entries[i]->value);
old_entries[i] = old_entries[i]->next;
}
}
free(old_entries);
}
If I'm doing something that's inefficient (in terms of space and time), please let me know, as I am only in Bachelor's 3rd semester of CS and we have only started DSA this semester.
The thing you are doing by putting dummy elements at the beginning of each bin is a good idea, but you don't need to allocate such dummies with malloc(). You can just make the bin array an array of nodes instead of pointers to nodes. Then you have allocated the dummies when you have allocated the array. So you could define your hash table as
struct hash_table
{
int table_size;
struct list_node *list_arr;
};
(instead of using struct list_node **list_arr).
When you loop through the bins in the initialisation, you have to set the bins' next pointer to NULL, but not allocate them.
struct hash_table
*initialize(unsigned int table_size)
{
struct hash_table *H = malloc(sizeof(*H));
H->list_arr = malloc(sizeof(*H->list_arr)*table_size);
H->table_size = table_size;
for(unsigned int i = 0; i<table_size; i++)
{
// no malloc here!
H->list_arr[i].next = NULL;
}
return H;
}
Anyway, that is not pertinent to the rehashing, just a suggestion. But because you have the dummy elements as bins, you can refactor your code (that is the reason I think the dummies are such a good idea). You can get the bin from the table and work from there, without worrying about the table itself after that. You can get the relevant bin for a key with
struct list_node *get_bin(struct hash_table *H, const char *key)
{
unsigned int index = hash(key, H->table_size);
return &H->list_arr[index];
}
and you can find the node in a bin with
struct list_node *find_node(struct list_node *bin, const char *key)
{
for (struct list_node *current = bin->next;
current;
current = current->next) {
if(strcmp(current->key,key)==0) return current;
}
return 0;
}
and, for example, simplify insertion to
void prepend_node(struct list_node *node, struct list_node *bin)
{
node->next = bin->next;
bin->next = node;
}
void insert(struct hash_table *H, const char *key, const char *value)
{
struct list_node *bin = get_bin(H, key);
struct list_node *node = find_node(bin, key);
if (node) {
// update node
free(node->value);
node->value = malloc(strlen(value)+1);
strcpy(node->value,value);
} else {
// prepend new node
prepend_node(new_node(key, value), bin);
}
}
where the new_node() function looks like
struct list_node *new_node(const char *key, const char *value)
{
struct list_node *node = malloc(sizeof *node);
if (!node) abort(); // add some error handling here
node->key = malloc(strlen(key)+1);
if (!node->key) abort(); // add some error handling here
strcpy(node->key,key);
node->value = malloc(strlen(value)+1);
if (!node->value) abort(); // add some error handling here
strcpy(node->value,value);
return node;
}
Because the bins are embedded in the array, you can safely assume in all the functions that they aren't NULL, which can save you from testing some special cases.
It is not shorter code, because I split it into several functions, but in my opinion, it is more readable when each function does one simple thing. Here, getting the bin, finding the key in a bin, creating a node, pretending to a bin, etc. With "raw" malloc() and strcpy() and such, scattered through the code, it is harder to track that everything works correctly. The total lines of code grew, but each function is shorter and simpler. And you can get away with it, because you can work on bins as lists, without accessing the hash table array, exactly because all bins have a dummy head element.
You can now rewrite rehash() to just prepend to bins. You know that all the keys in the old bins are unique, so you don't need to check anything. You just put each node at the front of its new bin:
struct hash_table *rehash(struct hash_table *H)
{
unsigned int old_size = H->table_size;
struct list_node *old_entries = H->list_arr;
free(H); // You forgot to free this one!
H = initialize(2*old_size);
for(unsigned int i = 0; i<old_size; i++)
{
struct list_node *old_bin = &old_entries[i];
for (struct list_node *node = old_bin->next;
node; node = node->next) {
// just prepend to new bin; the key should be unique
prepend_node(node, get_bin(H, node->key));
}
}
free(old_entries);
return H;
}
I added a free(H) because you forgot to free memory for H, but it would be more efficient to update H without creating a new table. You can separate initialisation and allocation. But you do not gain terribly much as initialising the bins is the time-consuming part.
Speaking of freeing, though. Remember to write a function for freeing a hash table (that remembers to free the bins, including all the nodes). Don't use it with rehashing, of course, if you free H before you update it--you need to keep the nodes around--but you do want such a function.
I got a memory leak in my program, and I can't understand why. I got a 4 size array of linked lists, and valgrind says there is a memory leak.
Here is my struct:
struct node {
achievementMen100m player;
char* playerName;
Men100mAchievement playerAchiInRound;
char*currentRound;
struct node *head;
struct node *next;
} node, *Node;
Here is my allocation in the create function:
for(int i=0; i<4;i++){
OG->games->head->phases[i] = malloc(sizeof(struct node)); //VALGRIND SAYS MEMORY ALLOCATED HERE NOT FREED!//
OG->games->head->phases[i]->head=NULL;
OG->games->head->phases[i]->next=NULL;
OG->games->head->phases[i]->playerAchiInRound = 0;
}
Here is my free-list function:
void listDestroy(struct node * list) {
struct node * currentPlayer = list;
struct node * temp;
while (currentPlayer != NULL) {
temp = currentPlayer;
currentPlayer=currentPlayer->next;
free(temp->playerName);
free(temp);
}
list = NULL;
free(list);
}
And this is the free function of the ADT:
void olympicGamesDestroy(OlympicGames OG) {
if (OG == NULL) {
return;
}
if (OG->games == NULL) {
free(OG);
return;
}
if (OG->games->head == NULL) {
free(OG->games);
free(OG);
return;
}
for (int i=0; i<4;i++) {
listDestroy(OG->games->head->phases[i]->head);
}
free(OG->games->next);
free(OG->games->head);
free(OG->games);
free(OG);
}
update
here is my entire .h file
typedef struct men100 {
Men100mAchievement olympicMinimum;
Men100mAchievement olympicSkipPre;
char* roundNames[4];
struct node* phases[4];
} men100, *Men100;
typedef struct gameList {
int name;
men100* head;
struct gameList *next;
} gameList, *GameList;
typedef struct olympicGames {
GameList games;
int numOfGames;
} olympicGames, *OlympicGames;
Your void olympicGamesDestroy(OlympicGames OG) looks strange!
You are allocating at OG->games->head->phases[i].
So, where are you freeing them? You are only working on OG->games->head->phases[i]->head and not on OG->games->head->phases[i].
Show the actual OlympicGames data structure.
UPDATE:
I don't have much time to verify the whole code:
But you can try the following:
for(int i=0; i<4; i++)
{
listDestroy(OG->games->head->phases[i]->head);
free(OG->games->head->phases[i]); // you need this
}
I'm working on assignment for an operating systems class. We are given code to use to help us with our assignment, but I have little programming experience with C, and I can't figure out how to use it. What I'm trying to do is print the information at the head of the list. The list is a list of structs defined as
typedef struct
{
char name[NAME_MAX];
int lifetime;
} pcb_t;
int
List_head_info ( List_t *list, void **data )
{
int all_ok = 0;
*data = NULL;
if ((list != NULL) && (list->head != NULL)) {
*data = list->head->data;
all_ok = 1;
}
return all_ok;
}
I tried to display them with:
printf("test: %s", List_head_info(&processes, (void *)pcb)->name);
but I am given the error invalid type argument a->a when compiling.
When you call List_head_info(), you will get back two things:
A pointer (void *) to the head data, or NULL.
A status indicating whether the pointer is non-NULL.
If it returns successfully, you can convert (coerce, or cast) the void * to a pcb_t * and then use that to print the data.
How would I do that specifically?
Probably something a bit like this:
List_t list;
...code to initialize and maybe add things to the list...
void *head_data = 0;
if (List_head_info(&list, &head_data))
{
pcb_t *item = (pcb_t *)head_data;
printf("Lifetime: %.2d; Name: %s\n", item->lifetime, item->name);
}
Strictly, the initialization of head_data is superfluous; the code in List_head_info() always sets the value at least once (to NULL or 0) and sometimes twice (the second time to the data component of the head item on the list).
This is 'example code' with enough information in it to compile. I've 'reverse engineered' the list structures enough to make sense; the actual implementation will be different, of course. This compiles cleanly under fairly stringent GCC warning levels, with GCC 4.1.2 and 4.7.0 on Mac OS X 10.7.4. AFAICS, it avoids some complex issues related to 'strict aliasing' which you really don't want to have to worry about at this stage.
#include <stdio.h>
enum { NAME_MAX = 40 };
typedef struct Node Node;
struct Node
{
void *data;
Node *next;
};
typedef struct
{
Node *head;
Node *tail;
} List_t;
typedef struct
{
char name[NAME_MAX];
int lifetime;
} pcb_t;
extern int List_head_info(List_t *list, void **data);
extern void another_func(List_t processes);
void another_func(List_t list)
{
void *head_data = 0;
if (List_head_info(&list, &head_data))
{
pcb_t *item = (pcb_t *)head_data;
printf("Lifetime: %.2d; Name: %s\n", item->lifetime, item->name);
}
}
int
List_head_info ( List_t *list, void **data )
{
int all_ok = 0;
*data = NULL;
if ((list != NULL) && (list->head != NULL)) {
*data = list->head->data;
all_ok = 1;
}
return all_ok;
}
Hey,
I'm a beginner in C and tried to implement my own linked list implementation, that basically looks like this:
struct Element
{
void *value;
struct Element *next;
};
typedef struct
{
struct Element *first;
struct Element *last;
unsigned int size;
} LinkedList;
void LinkedList_init(LinkedList *this)
{
this->size = 0;
this->first = NULL;
this->last = NULL;
}
void LinkedList_add(LinkedList *this, void *value)
{
struct Element *node = malloc(sizeof(struct Element));
node->value = value;
node->next = NULL;
if (this->size == 0)
this->first = this->last = node;
else
{
this->last->next = node;
this->last = node;
}
this->size++;
}
So in short, I want a linked list that can hold arbitrary types - I heard, this is possible in C by using void pointers.
The problem now arises, when I want to use that implementation, for example with a structure as value:
typedef struct
{
int baz;
} Foo;
int main(void)
{
LinkedList list;
Foo bar;
bar.baz = 10;
LinkedList_init(&list);
LinkedList_add(&list, (void *) &bar);
/* try to get the element, that was just added ... */
Foo *firstElement = (Foo *)list.first;
/* ... and print its baz value */
printf("%d\n", firstElement->baz);
return 0;
}
The last printf call just prints values like -1077927056, which look like a memory address. So it's probably a problem with pointers. After searching the web the last few days for a similar issue on the web (I had no luck with that), I tried to throw my own logic away and tested various random *& combinations. Turns out, that was a dead end, too. :(
It's probably something simple for a more experienced C programmer, but I just can't find the answer. Please help :D
list.fist is a struct Element.
Try:
Foo *firstElement = (Foo *)(list.first->value);