stddef.h Linux определяет offsetof()
как:
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
тогда как статья Wikipedia о offsetof()
(http://en.wikipedia.org/wiki/Offsetof) определяет его как:
#define offsetof(st, m) \
((size_t) ( (char *)&((st *)(0))->m - (char *)0 ))
Почему вычитают (char *)0
в версии Википедии? Есть ли какой-либо случай, где это на самом деле имело бы значение?
Первая версия преобразует указатель в целое число с преобразованием, что не является переносимым.
Вторая версия более переносима для более широкого круга компиляторов, потому что она полагается на арифметику указателей компилятора для получения целочисленного результата вместо преобразования типов.
Кстати, я был редактором, добавившим исходный код в статью Wiki, которая была формой Linux. Позже редакторы изменили его на более портативную версию.
Стандарт не требует, чтобы указатель NULL оценивался как битовая комбинация 0, но может оценивать значение, зависящее от платформы.
Выполнение вычитания гарантирует, что при преобразовании в целое значение NULL будет 0.