21

Linuxカーネルのcontainer_of()マクロは次のように定義されています。

#define container_of(ptr, type, member) ({ \
        const typeof( ((type*)0)->member) * __mptr =(ptr);\
        (type*)( (char*)__mptr - offsetof(type,member) );})

なぜこれは((type*)0)->memberではなく、を使用するの(type*)->memberですか?

4

2 に答える 2

20

なぜこれが((type *)0)->メンバーであり、(type *)->メンバーではないのか

構文が無効であるという理由だけ(type*)->memberで、したがってtypeof不可能になります。したがって、NULLポインタを使用しますが、とにかく逆参照しませんtypeof。メンバーを参照できるように使用されます。


これがどのように機能するか:

  • このtypeofトリックは、メンバーのタイプのポインターを宣言するために使用されます。このポインタは、呼び出し元から渡されたポインタで初期化されます。

  • 構造体のそのメンバーのオフセットは、ポインターのアドレスから減算されます。これにより、含まれているオブジェクトのアドレスが生成されます。


微妙な問題:なぜ取り除いてtypeof、ただやってみませんかptr - offsetofchar *とにかくキャストしますよね?その場合、あなたは何でも渡すことができptr、コンパイラは何も言わないでしょう。したがって、すべてtypeofが(基本的な)タイプチェックのためにあります。

于 2012-12-05T12:42:39.087 に答える
7

type*は型であり、構造の有効なインスタンスではないためです。

ゼロへのポインターは適切なインスタンスを取得するために使用されますが、typeof実行時ではなくコンパイル時に解決されるため、ポインターで使用されるアドレスは適切または有効なアドレスである必要はありません。

于 2012-12-05T12:43:31.273 に答える