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?