4

私は、offsetof MACRO の実装の説明について、非常に長く懸命に検索してきました (リンクは最後に)。

#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)

特に、構造体のメンバーのオフセットを取得するための NULL の逆参照。多くの記事では、NULL ポインターは実際には実際には逆参照されないと言ってその理由をごまかしていますが、それは私には意味がありません。

ここに私が理解しようとしたリンクのいくつかがあります:

  1. http://www.viva64.com/en/b/0301/
  2. http://www.embedded.com/design/prototyping-and-development/4024941/Learn-a-new-trick-with-the-offsetof--マクロ
  3. http://www.geeksforgeeks.org/the-offsetof-macro/
  4. C の offsetof マクロはどのように機能しますか?
  5. NULL ポインターを逆参照すると、C/C++ でプログラムがクラッシュすることが保証されますか?

私が探して理解しようとしているのは、コンパイラが MACRO 定義をどのように解釈するかを段階的に理解することです。最終的には、NULL ポインターが実際に逆参照されていない方法を説明します。

編集:他の質問が私の質問に答えたとしても、元の投稿で指摘されているように、それらは私には意味がありません。@dasblinkenlight による回答は、他の質問への回答で私が抱えていた正確な問題、つまり、実際にポインターを逆参照していないのはどうしてなのかを明らかにしています。

4

1 に答える 1

8

特に、構造体のメンバーのオフセットを取得するための NULL の逆参照。

operator の効果は operatorによって元に戻されるため、ポインターの逆参照は行われません。->&

  • これは、次の逆参照になりますNULL((TYPE *)0)->MEMBER
  • その前に追加&すると、アドレス計算になります。&((TYPE *)0)->MEMBER

多くの記事では、NULL ポインターは実際には実際には逆参照されないと言って、その理由をごまかしていますが、それは私には意味がありません。

次の例を説明として考えてください。

int a;
int *p = &a;
int b = *p;     // <<== This is a dereference
int *q = &(*p); // <<== This is not a dereference

2 つの演算子*&は、互いの効果を元に戻します。演算子はand->の上にある「シンタックス シュガー」であるため、その効果も元に戻すことができます。*.&

コンパイラが式を認識するsomePointer->aと、ポインターの数値を取得し、somePointermember のオフセットを追加して、a操作できるメモリ内の場所を学習します。メモリ内の場所に対して実行できる操作は 3 つあります。

  1. それを読んで
  2. 書いてください
  3. その住所を知る

項目 1 と 2 (読み取りと書き込み) は、逆参照を構成します。ただし、項目 3 は、特定のアドレスのメモリがアクセスされないため、逆参照ではありません。

aマクロは基本的に、ベース アドレスがゼロであると仮定してメンバーのアドレスを計算するようにコンパイラに要求します。返されるのアドレスは、当然のオフセットaと等しくなります。aあなたがする必要があるのは、そのアドレスを取得することだけです。これは、 operator で行うことです&

于 2016-04-11T02:02:34.607 に答える