#author("2025-10-28T10:20:21+09:00","default:guest","guest")
#author("2025-10-28T10:21:39+09:00","default:guest","guest")
*参照元 [#u2248d71]
#backlinks

*説明 [#mf644141]
-パス: [[linux-5.15/include/linux/kernel.h]]

-ポインタが指す構造体のメンバ、それを含む構造体へのポインタを返す。
--例えば、
 struct example {
    int mem_a;
    char mem_b;
 };
 struct example hoge;
--このような構造体があったとき、
 int *mem_ptr = &hoge.mem_a;
--構造体のメンバへのポインタmem_ptrしか分からない状態からhogeへのポインタを得たいときにcontainer_ofを使う。
 struct example *ptr = container_of(mem_ptr, struct example, mem_a);
--するとptrが指す先(hoge.mem_a)を含む構造体へのポインタ(&hoge)が得られる。


**引数 [#b71627a5]
-ptr
--構造体のメンバへのポインタを指定する。
-type
--ptr に指定したポインタが指すメンバ、これを含む「構造体名」を指定する。マクロはここで指定した型のポインタを返す。
--ptrに指定したポインタが指すメンバ、これを含む「構造体名」を指定する。マクロはここで指定した型のポインタを返す。
---上記の例で言うと変数名のhogeではなくて、変数の型の名前struct exampleを指定する。
-member
--ptrに指定したポインタが指す「メンバ名」を指定する。
--typeに指定した型はmemberに指定した名前のメンバを持っていないとコンパイルエラーになる。
---上記の例で言うとポインタ変数mem_ptrではなく、struct example 構造体のメンバ名であるmem_aを指定する。
---上記の例で言うとポインタ変数mem_ptrではなく、struct example構造体のメンバ名であるmem_aを指定する。


**返り値 [#q3834c46]
-type *
--指定した構造体のメンバへのポインタ(ptrに指定する)が指すメンバ(メンバの名前はmemberに指定する)、これを含む構造体(構造体の型はtypeに指定する)へのポインタを返す。
--例えばlist_entry(a, struct hogehoge, b) とすれば、struct hogehoge *が返ってくる。


**参考 [#na45adb3]


*実装 [#v092b33c]

 /**
  * container_of - cast a member of a structure out to the containing structure
  * @ptr:	the pointer to the member.
  * @type:	the type of the container struct this is embedded in.
  * @member:	the name of the member within the struct.
  *
  */
 #define container_of(ptr, type, member) ({				\
 	void *__mptr = (void *)(ptr);					\

-ポインタ演算のためvoid *型の__mptrに変換する。

 	BUILD_BUG_ON_MSG(!__same_type(*(ptr), ((type *)0)->member) &&	\
 			 !__same_type(*(ptr), void),			\
 			 "pointer type mismatch in container_of()");	\

-ptrは、typeのmemberのポインタ型か、void *である必要がある。そうでなければビルドエラーにする。
--[[linux-5.15/BUILD_BUG_ON_MSG()]]
--[[linux-5.15/__same_type()]]

 	((type *)(__mptr - offsetof(type, member))); })

-構造体の先頭へのポインタを計算する。この値がマクロの戻り値となる。
--member を指すポインタから、メンバーのオフセットを引く。
メンバーのオフセットは構造体の先頭から、メンバーまでの距離なので、
メンバーのポインタから引いてやれば、構造体の先頭を指すポインタが得られる。
--memberを指すポインタから、メンバーのオフセットを引く。
メンバーのオフセットは構造体の先頭から、メンバーまでの距離なので、メンバーのポインタから引いてやれば、構造体の先頭を指すポインタが得られる。
 return -> ----   ----
           mem_a     |
           ----      | offset
           mem_b  ___|
           ----   <- __mptr
           mem_c
           ----
---offsetof マクロは構造体のメンバー(member)が構造体(type)の先頭から
どの位置にいるか(オフセット)をバイト数で返す。
---拡張構文ではなく C の標準的なマクロで、stddef.h で定義されている。
manpage offsetof(3) などを参照のこと。
---offsetofマクロは構造体のメンバー(member)が構造体(type)の先頭からどの位置にいるか(オフセット)をバイト数で返す。
---GCC拡張構文ではなく、stddef.hで定義されているCの標準的なマクロ。manpage offsetof(3) などを参照のこと。


*コメント [#g88406c7]

トップ   編集 差分 履歴 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS