ア | イ | ウ | エ | オ |
カ | キ | ク | ケ | コ |
サ | シ | ス | セ | ソ |
タ | チ | ツ | テ | ト |
ナ | ニ | ヌ | ネ | ノ |
ハ | ヒ | フ | ヘ | ホ |
マ | ミ | ム | メ | モ |
ヤ | ユ | ヨ | ||
ラ | リ | ル | レ | ロ |
ワ | ヰ | ヴ | ヱ | ヲ |
ン |
A | B | C | D | E |
F | G | H | I | J |
K | L | M | N | O |
P | Q | R | S | T |
U | V | W | X | Y |
Z | 数字 | 記号 |
Linuxで使われている、要素が含まれる構造体などのアドレスを得るためのマクロ。container_ofと全く同じ動きをするが、用途が違うため別名となっている。
マクロなので、使用するにはincludeが必要。
#include <linux/list.h>
include/linux/list.hで定義されている。
Linux 2.6では、次のような定義である。
#define list_entry(ptr, type, member) \ container_of(ptr, type, member)
つまり、container_ofの別名である。
Androidなどでも、他のディレクトリのヘッダーファイルでは、独自の定義をしていることもある。
最もシンプルな実装方法は次の通り。例えば次のような定義をするヘッダーファイルがあった。
#define list_entry(link, type, member) \ ((type *)((char *)(link)-(unsigned long)(&((type *)0)->member)))
少し分かりにくいが、「&((type *)0)->member」は、アドレス0からのmemberの位置、つまりmemberの構造体内オフセットを示している。
構造体中のにあるメンバーのポインターから、そのメンバーの構造体中の位置(オフセット)を引き算することで、その構造体の先頭アドレスを得、それに構造体のキャストをして構造体へのポインターに変えてしまうというマクロである。
list_entryは、list_headと組み合わせて使用される。
struct list_headは、前後へのポインターのみを持つ連結リストである。for文などを使って順次アクセスすることが可能だが、このポインターから実際の構造体などを取り出すためには、ちょっとしたテクニックが必要である。このために、構造体の先頭アドレスを得るためのマクロとしてlist_entryが定義されている。
struct list_head *から元の構造体を取り出すには、次の引数を設定する。
こうすると、取り出したい構造体へのポインターが出て来るのである。
計算によって構造体のアドレスを求めるため、struct list_head *は、構造体の中のどこにあってもよい。構造体の中に入っていれば、それだけでその構造体を取り出せる。
登録するリストがstruct list_head data_list;として定義されているとすると、次のように使う。
struct list_head *ptr; struct data_struct *entry; for (ptr = data_list.next; ptr != &data_list; ptr = ptr->next) { entry = list_entry(ptr, struct data_struct, node); printf("%d\n", entry->id); }
for文にすると煩雑なので、list_for_eachマクロを使うことができる。
#define list_for_each(pos, head) \ for (pos = (head)->next; pos != (head); pos = pos->next)
下は上と同義である。
struct list_head *ptr; struct data_struct *entry; list_for_each(ptr, &data_list) { entry = list_entry(ptr, struct data_struct, node); printf("%d\n", entry->id); }
このようにして、struct list_headのポインターから、list_entryを使うことで各エントリーを得ることができる。
for文の中では、ポインター変数ptrに、struct list_headへのポインターが順次代入される。
さて、このptrはあくまでstruct list_headへのポインターだが、次の手順で、この変数のある構造体を得ることが可能である。
オフセットを得て引き算をしてキャストをするまでの一式が、list_entryマクロとして実装されている。
このトリッキーな計算のためには、ptr、構造体名、構造体中の変数名の三要素があれば良いことから、list_entryマクロの引数も、この三つとなっている。
コメントなどを投稿するフォームは、日本語対応時のみ表示されます