地方エンジニアの学習日記

興味ある技術の雑なメモだったりを書いてくブログ。たまに日記とガジェット紹介。

container_ofマクロ

container_ofマクロは、Linux Kernelで用いられ、「構造体メンバポインタ」から「そのメンバを含む構造体の先頭ポインタ」を得られるマクロ。

linuxカーネルで頻出の連結リストの実装はこんな感じ。

struct list_head {
    struct list_head *next, *prev;
};

これを使用したい構造体の中にメンバとして保持することで使用することができる。

struct item {
    int value;
    struct list_head list;
};

これだけだとlist_headのポインタしか見つからないのでその点を解決してるのが以下のcontainer_ofマクロ

github.com

#define container_of(ptr, type, member) ({                \
   void *__mptr = (void *)(ptr);                 \
   BUILD_BUG_ON_MSG(!__same_type(*(ptr), ((type *)0)->member) &&   \
            !__same_type(*(ptr), void),           \
            "pointer type mismatch in container_of()"); \
   ((type *)(__mptr - offsetof(type, member))); })

構造体のメンバーのアドレスと構造体の型宣言と構造体のメンバーの名前を渡せば構造体そのもののアドレスを返してくれるマクロ。

ぱっと見は黒魔術にしか見えない。。。

構造体Aのメンバー名を渡すことで親構造体を探してくれるって感じ。