I am implementing a stack that does not require memory allocation and can take any struct as long as it embeds a special struct. Similar to GNU's List implementation.
The struct that any struct must embed to work in the stack is:
struct stack_elem {
struct stack_elem *next;
};
The struct that I would like to be used with the stack is:
struct node {
double number;
char character;
int isNumber;
struct stack_elem elem;
};
So the stack would look like this:
node: node:
+---------+ +---------+
|number | |number |
+---------+ +---------+
|character| |character|
+---------+ +---------+
|isNumber | |isNumber |
+---------+ +---------+
|elem | |elem |
| *next |----->| *next |
+---------+ +---------+ etc....
I am writing a macro called stack_entry
to convert the embedded elem
struct to its container node
struct. Here's what I've tried so far. stack_entry
will be used as follows:
struct stack_elem *top = peek(&stack);
struct node *converted_node = stack_entry(top, struct node, elem);
stack_entry
will take a pointer to the stack_elem
, the type of the node to be converted to and the name of the member field of the element in that node. I tried several ways to do it but none work. I realized that STACK_ELEM
points to the next
item and so I tried just subtracting the offset of elem
from struct node
and that did not work. Here are a few things I tried that did not work either:
#define stack_entry(STACK_ELEM, STRUCT, MEMBER) \
((STRUCT *) &(STACK_ELEM) - offsetof (STRUCT, MEMBER))
#define stack_entry(STACK_ELEM, STRUCT, MEMBER) \
((STRUCT *) ((uint8_t *) &(STACK_ELEM)->next \
- offsetof (STRUCT, MEMBER)))
What would be the correct arithmetic? Why isn't subtracting the offset of next
, hence the offset of elem
, yielding node if its the last element in the struct?
GNU List list_entry
macro is defined as:
#define list_entry(LIST_ELEM, STRUCT, MEMBER) \
((STRUCT *) ((uint8_t *) &(LIST_ELEM)->next \
- offsetof (STRUCT, MEMBER.next)))
How does this work? Why is next
involved in here when its supposed to grab the container struct within the same node, and not the next
one?