A
Arto Huusko
Hello,
I'm wondering about the portability and correctness of the
following scenario.
I have a generic doubly linked list structure, and it contains
generic nodes that look like this:
struct node
{
struct node *head;
struct node *tail;
};
struct list
{
struct node *first;
struct node *last;
};
Now, I want to use the generic list and node structures so that
- The list and its nodes stay completely generic.
That means I can have generic functions like
add_head(struct list *, struct node *);
Any list can be traversed and examined and manipulated
with the generic functions, as long as the operations
are stay on the generic level.
- The nodes can contain application specific data. That is:
the node structure is extended by adding application specific
fields, which can only be accessed if the application knows
what kind of node it is using.
Application specific node would look like
struct my_app_node
{
struct node node;
int datafield1;
char *datafield2;
etc.
};
Now, an application could do:
struct list mylist;
struct my_app_node node1;
struct my_app_node node2;
init_list(&mylist);
add_head(&mylist, (struct node *)&node1);
add_head(&mylist, (struct node *)&node2);
So, is this correct ISO C? Is this portable?
I know that I could do also:
add_head(&mylist, &node1.node);
But, of course, both questions boil down to: can I trust
that offset of "node" inside my_app_node is 0? And also,
does the compiler let me get away with the cast?
I also do know that a certainly correct solution would be:
struct node
{
struct node *next;
struct node *prev;
void *data;
};
struct my_app_node
{
struct node node;
/* data fields follow */
};
struct my_app_node mynode;
mynode.node.data = &mynode;
But in this scenario I'm completely vasting one pointer.
(This all motivated by GCC 3.3's strict alignment stuff...)
I'm wondering about the portability and correctness of the
following scenario.
I have a generic doubly linked list structure, and it contains
generic nodes that look like this:
struct node
{
struct node *head;
struct node *tail;
};
struct list
{
struct node *first;
struct node *last;
};
Now, I want to use the generic list and node structures so that
- The list and its nodes stay completely generic.
That means I can have generic functions like
add_head(struct list *, struct node *);
Any list can be traversed and examined and manipulated
with the generic functions, as long as the operations
are stay on the generic level.
- The nodes can contain application specific data. That is:
the node structure is extended by adding application specific
fields, which can only be accessed if the application knows
what kind of node it is using.
Application specific node would look like
struct my_app_node
{
struct node node;
int datafield1;
char *datafield2;
etc.
};
Now, an application could do:
struct list mylist;
struct my_app_node node1;
struct my_app_node node2;
init_list(&mylist);
add_head(&mylist, (struct node *)&node1);
add_head(&mylist, (struct node *)&node2);
So, is this correct ISO C? Is this portable?
I know that I could do also:
add_head(&mylist, &node1.node);
But, of course, both questions boil down to: can I trust
that offset of "node" inside my_app_node is 0? And also,
does the compiler let me get away with the cast?
I also do know that a certainly correct solution would be:
struct node
{
struct node *next;
struct node *prev;
void *data;
};
struct my_app_node
{
struct node node;
/* data fields follow */
};
struct my_app_node mynode;
mynode.node.data = &mynode;
But in this scenario I'm completely vasting one pointer.
(This all motivated by GCC 3.3's strict alignment stuff...)