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--macro
  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

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

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

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

第 1 项和第 2 项(阅读和写作)构成解除引用。然而,第 3 项不是取消引用,因为特定地址的内存没有被访问。

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

于 2016-04-11T02:02:34.607 回答