如何以可移植的方式从指向结构成员的指针计算指向结构开头的指针?

How can one calculate a pointer to the beginning of a struct from a pointer pointing at a member of the struct in a portable way?

假设 T1T2 是两种类型,并给出以下结构:

struct s
{
  T1 x;
  T2 y;
}

此外,假设我们有一个类型为 struct s:

的对象
struct s a;

据此,我们可以计算出指向对象第二个结构成员的指针:

T2 *q = &s.y;

我正在寻找的是一种可移植的方法,可以从 q 类型 struct s * 的指针 p 进行计算,使得 p 指向对象 a.

给定 T2 *q = &s.y;,然后 char *x = (char *) q - offsetof(struct s, y); 定义一个指向 s 的第一个字节的 xoffsetof 宏在 <stddef.h>.

中定义

然后人们可能会期望 struct s *p = (struct s *) x; 定义一个指向 sp,这取决于人们希望如何迂腐地解释 C 标准。 (将指向 char 的指针转换为指向其第一个字节的结构的指针并未由标准明确定义。我们可以采用 C 2018 6.3 中指针“转换回来”的标准规范.2.3 7,到它的原始类型来涵盖这种情况。)我希望它能在所有正常的 C 实现中工作。

T2 *py = &z.y

T1 *px = (T1 *)((char *)py - ((char *)&z.y - (char *)&z.x));

您正在寻找container_of();来自 Wikipedia

#define container_of(ptr, type, member) ((type *)((char *)(1 ? (ptr) : &((type *)0)->member) - offsetof(type, member)))

或更简单但不太安全的方法

#define container_of(ptr, type, member) ((type *)((char *)(ptr) - offsetof(type, member)))

在你的情况下,你可以像这样应用它

struct *s = container_of(q, struct s, y);