I'm trying to implement a linked list like this:
typedef struct SLnode
{
void* item;
void* next;
} SLnode;
typedef struct DLnode
{
void* item;
void* next;
struct DLnode* prev;
} DLnode;
typedef struct LinkedList
{
void* head; /*SLnode if doubly_linked is false, otherwise DLnode*/
void* tail; /* here too */
bool doubly_linked;
} LinkedList;
And I want to access it like this:
void* llnode_at(const LinkedList* ll, size_t index)
{
size_t i;
SLnode* current;
current = ll->head;
for(i = 0; i < index; i++)
{
current = current->next;
}
return current;
}
So my question is:
In case this doesn't work, are there any other ways of doing something like this? I read that unions might work, but this code should also run in C89, and afaik reading a different union member than last written to is UB there.
So you are trying to build subclasses in C. A possible way is to make the base struct to be the first element of the child struct, because in that case C standard explicitely allows casting back and forth between those 2 types:
6.7.2.1 Structure and union specifiers
§ 13 ... A pointer to a structure object, suitably converted, points to its initial member (or if that member is a bit-field, then to the unit in which it resides), and vice versa...
The downside is that you need a cast to the base class to access its members:
Example code:
typedef struct SLnode
{
void* item;
void* next;
} SLnode;
typedef struct DLnode
{
struct SLnode base;
struct DLnode* prev;
} DLnode;
You can then use it that way:
DLnode *node = malloc(sizeof(DLnode));
((SLnode*) node)->next = NULL; // or node->base.next = NULL
((SLnode *)node)->item = val;
node->prev = NULL;