Почему вызов offsetof() для элемента-указателя является незаконным?

Отсюда Я знаю, что в 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.

Обновлено: я сделал неправильное предположение, и упомянутая ссылка недействительна. Проблема заключалась в заполнении структуры, как было объяснено.

Непонятно, что вы подразумеваете под «членом указателя». MEMBER может быть любым именем поля, которое является членом структуры TYPE. Возможно, вы захотите привести несколько примеров того, что вы имеете в виду.

Eugene Sh. 09.05.2024 21:51

Вопрос, на который вы ссылаетесь, относится к членам C++. структуры в C и C++ сильно различаются.

dbush 09.05.2024 21:54

Пример, который вы приводите, совершенно хорош. Он дает разные значения, потому что добавляет дополнение после a всякий раз, когда ptr является 64-битным, чтобы обеспечить правильное выравнивание.

Eugene Sh. 09.05.2024 22:02

В сообщении, которое вы цитируете, не говорится о члене структуры, имеющем тип указателя. Речь идет о переменной типа указателя на член. Однако говорить о разных вещах может быть сложно из-за того, что одни и те же слова составлены по-разному, чтобы назвать их обоих. И используемый там термин «указатель члена» неоднозначен относительно того, к чему он относится.

Avi Berger 09.05.2024 22:03

@ЕвгенийШ. О, теперь я вижу. Совсем забыл об этом. Спасибо

user20158758 09.05.2024 22:07

@frippe Евгений уже объяснил это.

Barmar 09.05.2024 22:10
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
6
103
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Комментарий, на который вы ссылаетесь, предназначен для C++, а не C. Он не относится к C.

Кроме того, здесь не сказано, что offsetof нельзя использовать (не «вызывать»; это не функция) для члена-указателя (то есть члена структуры, который является указателем). Там написано, что offsetof нельзя использовать для указателя члена.

Указатель члена — это вещь C++, которой нет в C. Это особый вид указателя, который ссылается на член в контексте класса. (Это не автономный указатель, который можно использовать отдельно.)

Таким образом, причина, по которой вы не можете использовать offsetof для указателя члена в C, заключается в том, что в C такой вещи не существует.

Это из-за выравнивания. размер ptr, как и всех остальных указателей, равен 8, поэтому смещение члена ptr выравнивается до 8 байт.

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