MACRO的offset理解困难

mav*_*ick 4 c memory macros pointers offsetof

我一直在寻找很长很长的时间(最后的链接)来解释 offsetof MACRO 的实现:

#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
Run Code Online (Sandbox Code Playgroud)

特别是,取消引用 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. C offsetof 宏是如何工作的?
  5. 取消引用 NULL 指针是否保证会导致 C/C++ 中的程序崩溃?

我正在寻找并试图理解的是对编译器如何解释 MACRO 定义的逐步分解理解,这最终将解释 NULL 指针实际上没有被取消引用。

编辑:尽管其他问题回答了我的疑问,但正如原始帖子中所指出的那样,它们对我来说没有意义。@dasblinkenlight 的回答揭示了我在回答其他问题时遇到的确切问题,即我们实际上没有取消引用指针是怎么回事。

das*_*ght 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
Run Code Online (Sandbox Code Playgroud)

两个运算符*和&,取消彼此的效果。运算符->是*and之上的“语法糖” .,因此&也可以撤消其效果。

当编译器看到一个表达式时,somePointer->a它会获取指针的数值somePointer,加上成员的偏移量a,并了解您可以在内存中操作的位置。您可以对内存中的某个位置做三件事:

  1. 阅读
  2. 写下来
  3. 了解它的地址

第 1 项和第 2 项(读取和写入)构成取消引用。但是,第 3 项不是解引用,因为特定地址处的内存未被访问。

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