C: лучший способ сделать sizeof (((SomeStruct *) 0) - > some_member)?
Вопрос
Я хочу получить размер определенного члена в структуре.
sizeof (((SomeStruct *) 0) - > some_member)
работает для меня, но я чувствую, что, возможно, есть более хороший способ сделать это.
Я мог бы #define SIZEOF_ELEM (STRUCT, ELEM) sizeof (((STRUCT *) 0) - > ELEM)
, а затем использовать SIZEOF_ELEM (SomeStruct, some_member)
, но мне интересно, есть ли уже что-то лучше встроенное.
Мой конкретный вариант использования приведен в hsc2hs (привязки на Haskell C).
pokeArray (plusPtr context (#offset AVFormatContext, filename)) .
take (#size ((AVFormatContext *) 0)->filename) .
(++ repeat '\NUL') $ filename
Решение
То, что у вас есть, настолько чистое, насколько это возможно, если вы не можете гарантировать, что у вас есть переменная для разыменования. (Если вы можете, то, конечно, используйте только sizeof (var.member)
или sizeof (ptr-> gt; member)
, но в некоторых контекстах это не сработает где требуется постоянная времени компиляции.)
Давным-давно (около 1990 года) я столкнулся с компилятором, у которого было определено offsetof
, используя базовый адрес 0, и он вышел из строя. Я обошел проблему, взломав < stddef.h >
, чтобы использовать 1024 вместо 0. Но вы не должны сталкиваться с такими проблемами сейчас.
Другие советы
Я полагаю, у вас уже есть правильное решение. Вы можете найти свой stddef.h и посмотреть, как определяется offsetof, так как он делает очень похожую вещь. Р>
Помните, что вполне может быть разница между размером элемента и разницей между смещением этого элемента и следующего из-за заполнения.
В C ++ вы можете использовать sizeof (SomeStruct :: some_member), но это c, и у вас нет оператора разрешения области видимости. Насколько я знаю, вы написали настолько хорошо, насколько это возможно.
У Microsoft в одном из заголовков есть следующее:
#define RTL_FIELD_SIZE(type, field) (sizeof(((type *)0)->field))
Я не вижу причин делать что-то другое.
Они связали макросы для:
RTL_SIZEOF_THROUGH_FIELD()
RTL_CONTAINS_FIELD()
и отличный:
CONTAINING_RECORD()
, который помогает реализовать общие списки в прямом C, не требуя, чтобы поля ссылок были в начале структуры. См. Эту статью «Ядро ядра» для получения дополнительной информации. р>