Необходимо получить смещение между структурой и одним из ее полей в C - PullRequest
1 голос
/ 16 марта 2011

Название темы также может быть «Достаточно ли size_t для хранения адреса?»

Я пытаюсь получить смещение между структурой и одним из ее полей, и я использую переменную size_t для хранения смещения:

size_t offset = (size_t)&struct.field - (size_t)&struct;

Я знаю, что это как бы принудительно, мне просто интересно, могу ли я позже столкнуться с какой-то ошибкой из-за этого. Я знаю, что мог бы сделать то же самое, используя int, но мне интересно, может ли он содержать адрес в 64-битной системе.

Что вы думаете об этом?

Ответы [ 4 ]

7 голосов
/ 16 марта 2011

Используйте макрос offsetof, найденный в <stddef.h>.

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

3 голосов
/ 16 марта 2011

Используйте #include <stddef.h> ... offsetof(struct foo, field).Он определен как тип size_t.size_t не обязательно достаточно большой, чтобы содержать любой адрес, но он достаточно большой, чтобы содержать любое смещение в структуре, потому что он достаточно большой, чтобы содержать sizeof (любую структуру).

0 голосов
/ 16 марта 2011

Пока все элементы «исправлены» во время компиляции, вы будете в безопасности. Тем не менее, ваш код будет трудно поддерживать, и, как правило, таких действий следует избегать. Это рискует связать ваш код с определенной архитектурой, поскольку в конечном итоге одно из полей изменится, создавая проблемы, если все остальные вычисленные смещения не будут соответствующим образом обновлены.

Поскольку код имеет тенденцию жить дольше, чем мы думаем, шансы, что некоторые усилия по обслуживанию в конечном итоге исправят одно из значений, почти наверняка. Это нанесло бы ущерб (намного позже) обновлению порядка полей.

Я сохранил такой код. Я рекомендую сделать это по-другому, без необходимости знать точное выравнивание полей в коде.

0 голосов
/ 16 марта 2011

Чтобы сделать это вручную, вы можете сначала рассмотреть возможность вычитания указателя и size_t приведение ко второму, вот так:

size_t offset = (size_t)((void*)&struct.field - (void*)&struct);
...