Отсюда Я знаю, что в C
незаконно вызывать offsetof
по указателю, но почему это неопределенное поведение? Стандартная реализация
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
кажется, подходит даже для указателя MEMBER
, я не могу понять, почему это не работает.
Пример архитектуры, где int
— 4 байта:
#include <stddef.h>
#include <stdio.h>
struct foo {
int a;
int *ptr;
};
int main() {
printf("Offset of ptr: %zu\n", offsetof(struct foo, ptr));
return 0;
}
Этот код вернет 8, тогда как если бы ptr
было просто int
, он вернул бы 4. Но в обоих случаях этот член имеет одно и то же смещение, равное 4.
Обновлено: я сделал неправильное предположение, и упомянутая ссылка недействительна. Проблема заключалась в заполнении структуры, как было объяснено.
Вопрос, на который вы ссылаетесь, относится к членам C++. структуры в C и C++ сильно различаются.
Пример, который вы приводите, совершенно хорош. Он дает разные значения, потому что добавляет дополнение после a
всякий раз, когда ptr
является 64-битным, чтобы обеспечить правильное выравнивание.
В сообщении, которое вы цитируете, не говорится о члене структуры, имеющем тип указателя. Речь идет о переменной типа указателя на член. Однако говорить о разных вещах может быть сложно из-за того, что одни и те же слова составлены по-разному, чтобы назвать их обоих. И используемый там термин «указатель члена» неоднозначен относительно того, к чему он относится.
@ЕвгенийШ. О, теперь я вижу. Совсем забыл об этом. Спасибо
@frippe Евгений уже объяснил это.
Комментарий, на который вы ссылаетесь, предназначен для C++, а не C. Он не относится к C.
Кроме того, здесь не сказано, что offsetof
нельзя использовать (не «вызывать»; это не функция) для члена-указателя (то есть члена структуры, который является указателем). Там написано, что offsetof
нельзя использовать для указателя члена.
Указатель члена — это вещь C++, которой нет в C. Это особый вид указателя, который ссылается на член в контексте класса. (Это не автономный указатель, который можно использовать отдельно.)
Таким образом, причина, по которой вы не можете использовать offsetof
для указателя члена в C, заключается в том, что в C такой вещи не существует.
Это из-за выравнивания. размер ptr
, как и всех остальных указателей, равен 8,
поэтому смещение члена ptr
выравнивается до 8 байт.
Непонятно, что вы подразумеваете под «членом указателя».
MEMBER
может быть любым именем поля, которое является членом структурыTYPE
. Возможно, вы захотите привести несколько примеров того, что вы имеете в виду.