难以理解MACRO的偏移量

时间:2016-04-11 01:55:29

标签: c pointers memory macros 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--macro
  3. http://www.geeksforgeeks.org/the-offsetof-macro/
  4. How does the C offsetof macro work?
  5. Does dereference a NULL pointer guarantee to crash a program in C/C++?
  6. 我正在寻找和尝试理解的是一步一步,打破了对编译器如何解释MACRO定义的理解,这最终将解释NULL指针实际上是如何被解除引用的。

    编辑: 即使其他问题回答了我的问题,但正如原帖中指出的那样,它们对我有意义。 @dasblinkenlight的答案揭示了我对其他问题的问题,即我们实际上并没有解除引用指针的问题。

1 个答案:

答案 0 :(得分:4)

  

特别是,取消引用NULL以获取结构中成员的偏移量。

指针没有解除引用,因为运算符->撤消了运算符&的效果:

  • 这将取消引用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

两个运算符*&会消除彼此的影响。运算符->是一种&#34;语法糖&#34;在*.之上,&也可以撤消其效果。

当编译器看到表达式somePointer->a时,它会获取指针somePointer的数值,添加成员a的偏移量,并学习内存中可以操作的位置。你可以对记忆中的一个地方做三件事:

  1. 阅读
  2. 写下来
  3. 了解其地址
  4. 第1项和第2项(读写)构成解除引用。但是,第3项没有解除引用,因为不访问特定地址的内存。

    宏基本上要求编译器计算成员a的地址,假设基址为零。返回的a地址自然等于a的偏移量。您需要做的就是获取其地址,这是您对操作员&所做的。