Определение контейнера проверки типа макроса без использования расширений компилятора - PullRequest
2 голосов
/ 16 января 2020

Ниже приведен быстрый и простой способ определения макроса containerof с использованием только стандартных функций C:

#include <stddef.h>
#define containerof(ptr, type, member) \
((type *)((char *)(ptr)-offsetof(type, member)))

В другом распространенном определении макроса используется GNU C * 1005. * выражения выражения для дополнительной проверки типов:

#include <stddef.h>
#if __GNUC__+0 >= 3
#define containerof(ptr, type, member) ({ \
const __typeof__(((type *)0)->member) *containerof_memberptr_ = (ptr); \
(type *)((char *)(containerof_memberptr_)-offsetof(type, member)); })
#else
/* fallback */
#endif

Мой вопрос заключается в том, существует ли определение макроса с использованием только стандартных C функций, которые по-прежнему проверяют ссылочный тип ptr аргумент против типа member аргумента?

1 Ответ

3 голосов
/ 16 января 2020

Я пришел со следующим определением:

#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 или ошибки компиляции, если поддерживается компилятор.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...