container_of
Usage
container_of allows data structure code to be generic across multiple data types.
Data structures can be implemented without being tied to any data, and then embedded onto a container.
struct bstree
{
struct bstree* _parent;
struct bstree* _left;
struct bstree* _right;
};
struct album
{
char* name;
byte rating;
struct bstree bst;
};
The data structure code can then manipulate structures embedded onto the container, and container_of can be used to retrieve the data.
struct bstree* node = bstree_first(tree);
struct album* album = container_of(node, struct album, bst);
printf("%s\n", album->name);
How it works
Suppose a struct album a is stored in memory at address &a.
The value of a.bst will be stored at &a.bst, a certain offset bst_off from the start of the data.
If we have the address of a.bst, we can figure out the address of a: &a = &a.bst - bst_off.
&a &a.bst = &a + bst_off
v v
----+--------+--------+------------------------+----
...| name | rating | bst |...
----+--------+--------+------------------------+----
<-bst_off --------|
That is exactly what container_of does:
#define container_of(ptr, type, member) \
({ (type*)(((byte*)(ptr)) - offsetof(type, member)); })
((byte*)(&a.bst))Since the offset of a struct member is given in bytes, we cast the pointer to a
byte*before doing arithmetic.offsetof(struct album, bst)How many bytes away from the start of a struct of type
struct albumis the memberbststored. This is the value ofbst_off.(((byte*)(&a.bst)) - offsetof(struct album, bst))&a.bst - bst_offgives us&a, the address of the container we wanted to find.(struct album*)(((byte*)(&a.bst)) - offsetof(struct album, bst))Cast the result back to the type of the container.
API
#include <container_of.h>
Defines
-
container_of(ptr, type, member)
Calculates the address of a container given the address of a member.
Given the address of a member embedded in a container structure, calculates the address of the container.
- Parameters:
ptr – Pointer to the member.
type – Type of the container.
member – Name of the member.
- Returns:
Address of the container.