Зачем вычитать нулевой указатель в offsetof()?

Linux stddef.h определяет offsetof() как:

#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)

в то время как статья в Википедии о offsetof() ( http://en.wikipedia.org/wiki/Offsetof) определяет это как:

#define offsetof(st, m) \
    ((size_t) ( (char *)&((st *)(0))->m - (char *)0 ))

Зачем вычитать (char *)0 в версии википедии? Есть ли какой-нибудь случай, когда это действительно будет иметь значение?

2 ответа

Решение

Первая версия преобразует указатель в целое число с приведением, которое не является переносимым.

Вторая версия является более переносимой среди более широкого спектра компиляторов, поскольку она использует арифметику указателей компилятором для получения целочисленного результата вместо преобразования типа.

Кстати, я был редактором, который добавил исходный код к записи Wiki, которая была формой Linux. Позднее редакторы изменили его на более портативную версию.

Стандарт не требует, чтобы указатель NULL оценивался для битовой комбинации 0, но может оцениваться для значения, специфичного для платформы.

Выполнение вычитания гарантирует, что при преобразовании в целочисленное значение NULL равно 0.

Другие вопросы по тегам