Как можно вычислить указатель на начало структуры из указателя, указывающего на член структуры переносимым способом? - PullRequest
0 голосов
/ 22 декабря 2018

Предположим, T1 и T2 - два типа, и дана следующая структура:

struct s
{
  T1 x;
  T2 y;
}

Далее, предположим, что у нас есть объект типа struct s:

struct s a;

Исходя из этого, мы можем вычислить указатель на второй член структуры объекта:

T2 *q = &s.y;

Мне нужен портативный способ вычисления q указателя pвведите struct s *, чтобы p указывал на объект a.

Ответы [ 3 ]

0 голосов
/ 22 декабря 2018
T2 *py = &z.y

T1 *px = (T1 *)((char *)py - ((char *)&z.y - (char *)&z.x));
0 голосов
/ 22 декабря 2018

Вы ищете container_of();из Википедии

#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);
0 голосов
/ 22 декабря 2018

Учитывая T2 *q = &s.y;, тогда char *x = (char *) q - offsetof(struct s, y); определяет x, который указывает на первый байт s.Макрос offsetof определен в <stddef.h>.

Можно ожидать, что struct s *p = (struct s *) x; определит p, который указывает на s, в зависимости от того, насколько педантично вы хотите интерпретировать стандарт C.(Преобразование указателя в char в указатель на структуру, в которой он является первым байтом, не определено стандартом явно. Мы можем взять спецификацию стандарта, согласно которой указатель «преобразован обратно» в C 2018 6.3.2.37, в исходный тип, чтобы покрыть этот случай.) Я ожидаю, что он будет работать во всех нормальных реализациях C.

...