Как можно вычислить указатель на начало структуры из указателя, указывающего на член структуры переносимым способом?

Предполагать T1 а также T2 два типа и дается следующая структура:

struct s
{
  T1 x;
  T2 y;
}

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

struct s a;

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

T2 *q = &s.y;

То, что я ищу, это портативный способ расчета из q указатель p типа struct s * такой, что p указывает на объект a,

3 ответа

Решение

Дано 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.3 7, в свой первоначальный тип, чтобы охватить этот случай.) Я ожидаю, что он будет работать во всех обычных реализациях C.

Ты ищешь 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);
T2 *py = &z.y

T1 *px = (T1 *)((char *)py - ((char *)&z.y - (char *)&z.x));
Другие вопросы по тегам