Я пришел со следующим определением:
#include <stddef.h>
#define containerof(ptr, type, member) \
((type *)((char *)(0 ? &((type *)0)->member : (ptr))-offsetof(type, member)))
Любой несовместимый указатель, переданный в качестве аргумента ptr
, нарушает следующее ограничение условного оператора (C90 6.3.15 Условный оператор ):
- оба операнда являются указателями на квалифицированные или неквалифицированные версии совместимых типов
Я надеялся, что такое нарушение приведет к ошибке по умолчанию, однако G CC и clang только выдают предупреждение, и, похоже, в G CC не указана опция c -Werror=...
, чтобы превратить выдаваемое предупреждение в ошибку.
предупреждение: несоответствие типов указателей в условном выражении
clang удобно предоставляет такую опцию, которая называется -Werror=pointer-type-mismatch
. И G CC, и clang поддерживают широкую опцию -pedantic-errors
, которая также выдает предупреждение об ошибке.
Стандарт требует выдачи сообщения о диагностике c при нарушении ограничения (C90 5.1.1.3 Диагностика ), но это не означает, что компилятор должен выдавать ошибку в несовместимом коде.
В заключение, можно определить макрос containerof
, который не ' t полагаться на расширения языка, но все же дает некоторое поведение при проверке типа, будь то путем выдачи обязательного сообщения о диагностике c или ошибки компиляции, если поддерживается компилятор.