难以理解MACRO的偏移量
Difficulty in understanding the offsetof MACRO
我一直在努力寻找(链接在最后)对 offsetof MACRO 实现的解释:
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
特别是取消引用 NULL 以获得成员在结构中的偏移量。许多文章通过说 NULL 指针实际上从未真正取消引用来掩盖原因,但这对我来说没有意义。
以下是我尝试理解的一些链接:
- http://www.viva64.com/en/b/0301/
- http://www.embedded.com/design/prototyping-and-development/4024941/Learn-a-new-trick-with-the-offsetof--macro
- http://www.geeksforgeeks.org/the-offsetof-macro/
- How does the C offsetof macro work?
- Does dereference a NULL pointer guarantee to crash a program in C/C++?
我正在寻找并试图理解的是对编译器如何解释 MACRO 定义的逐步理解,最终将解释 NULL 指针实际上并没有被解除引用。
编辑:
尽管其他问题回答了我的问题,但它们对我来说并没有意义,正如原文 post 中指出的那样。 @dasblinkenlight 的回答阐明了我在回答其他问题时遇到的确切问题,即我们实际上并没有取消引用指针是怎么回事。
Particularly, the dereferencing of NULL to obtain the offset of the member in the structure.
没有指针的取消引用,因为运算符->
的效果被运算符&
:[=32=撤销了]
- 这将是对
NULL
的取消引用:((TYPE *)0)->MEMBER
- 在其前面加上
&
使其成为一个地址计算:&((TYPE *)0)->MEMBER
Many articles gloss over the reason by saying that the NULL pointer is actually never really dereferenced, but that doesn't make sense to me.
以这个例子为例:
int a;
int *p = &a;
int b = *p; // <<== This is a dereference
int *q = &(*p); // <<== This is not a dereference
*
和&
这两个运算符相互取消了效果。运算符 ->
是 *
和 .
之上的 "syntactic sugar",因此 &
也可以撤销其效果。
当编译器看到表达式 somePointer->a
时,它获取指针的数值 somePointer
,加上成员的偏移量 a
,并了解您在内存中的位置可以操作。您可以对内存中的某个位置执行三项操作:
- 阅读
- 写下来
- 了解它的地址
第 1 项和第 2 项(读取和写入)构成取消引用。然而,第 3 项并未取消引用,因为未访问特定地址处的内存。
该宏本质上要求编译器计算成员 a
的地址,假设基地址为零。 a
返回的地址自然就等于a
的偏移量。您需要做的就是获取它的地址,这就是您对运算符 &
.
所做的
我一直在努力寻找(链接在最后)对 offsetof MACRO 实现的解释:
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
特别是取消引用 NULL 以获得成员在结构中的偏移量。许多文章通过说 NULL 指针实际上从未真正取消引用来掩盖原因,但这对我来说没有意义。
以下是我尝试理解的一些链接:
- http://www.viva64.com/en/b/0301/
- http://www.embedded.com/design/prototyping-and-development/4024941/Learn-a-new-trick-with-the-offsetof--macro
- http://www.geeksforgeeks.org/the-offsetof-macro/
- How does the C offsetof macro work?
- Does dereference a NULL pointer guarantee to crash a program in C/C++?
我正在寻找并试图理解的是对编译器如何解释 MACRO 定义的逐步理解,最终将解释 NULL 指针实际上并没有被解除引用。
编辑: 尽管其他问题回答了我的问题,但它们对我来说并没有意义,正如原文 post 中指出的那样。 @dasblinkenlight 的回答阐明了我在回答其他问题时遇到的确切问题,即我们实际上并没有取消引用指针是怎么回事。
Particularly, the dereferencing of NULL to obtain the offset of the member in the structure.
没有指针的取消引用,因为运算符->
的效果被运算符&
:[=32=撤销了]
- 这将是对
NULL
的取消引用:((TYPE *)0)->MEMBER
- 在其前面加上
&
使其成为一个地址计算:&((TYPE *)0)->MEMBER
Many articles gloss over the reason by saying that the NULL pointer is actually never really dereferenced, but that doesn't make sense to me.
以这个例子为例:
int a;
int *p = &a;
int b = *p; // <<== This is a dereference
int *q = &(*p); // <<== This is not a dereference
*
和&
这两个运算符相互取消了效果。运算符 ->
是 *
和 .
之上的 "syntactic sugar",因此 &
也可以撤销其效果。
当编译器看到表达式 somePointer->a
时,它获取指针的数值 somePointer
,加上成员的偏移量 a
,并了解您在内存中的位置可以操作。您可以对内存中的某个位置执行三项操作:
- 阅读
- 写下来
- 了解它的地址
第 1 项和第 2 项(读取和写入)构成取消引用。然而,第 3 项并未取消引用,因为未访问特定地址处的内存。
该宏本质上要求编译器计算成员 a
的地址,假设基地址为零。 a
返回的地址自然就等于a
的偏移量。您需要做的就是获取它的地址,这就是您对运算符 &
.