【问题标题】:Why subtract null pointer in offsetof()?为什么要在 offsetof() 中减去空指针?
【发布时间】:2011-02-03 20:24:05
【问题描述】:

Linux 的 stddef.hoffsetof() 定义为:

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

offsetof() (http://en.wikipedia.org/wiki/Offsetof) 上的维基百科文章将其定义为:

#define offsetof(st, m) \
    ((size_t) ( (char *)&((st *)(0))->m - (char *)0 ))

为什么要在维基百科版本中减去(char *)0?在任何情况下,这实际上会有所作为吗?

【问题讨论】:

  • 您不应该使用/研究可能会引发未定义行为的代码,如上述。一个实现可以使用这种卑鄙的黑客,因为他们知道哪些类型的未定义行为会秘密起作用。但是“秘密工作”的东西是完全不可移植的。

标签: c pointer-arithmetic offsetof


【解决方案1】:

第一个版本通过强制转换将指针转换为整数,这是不可移植的。

第二个版本在更广泛的编译器中更易于移植,因为它依赖于编译器的指针运算来获得整数结果而不是类型转换。

顺便说一句,我是将原始代码添加到 Wiki 条目(即 Linux 表单)的编辑器。后来的编辑把它改成了更便携的版本。

【讨论】:

  • 感谢您的回复。后续问题“(size_t)((char *)0) 是否永远不会评估为 0?”发布于stackoverflow.com/questions/2581522/…
  • 有趣 - 但是第二个表达式真的更便携吗,因为空指针上的指针算术是未定义的?
  • 它更便携,因为它可以在更多 CPU 上运行。未定义(按标准)并不意味着它不适用于某些特定架构。
【解决方案2】:

该标准不要求 NULL 指针计算为位模式 0,但可以计算为特定于平台的值。

做减法保证当转换为整数值时,NULL 为 0。

【讨论】:

  • 不是这个原因;也可以使用除0 之外的任何合理常量。请参阅下面的答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-19
  • 1970-01-01
  • 2014-02-01
相关资源
最近更新 更多