Я ищу выражение типа sizeofbitfieldmemberinbits()
, которое
может быть рассчитан компилятором во время сборки
Термин, который вы описываете в Стандарте, называется " константное выражение ":
Постоянное выражение может быть оценено во время перевода, а не
время выполнения, и, соответственно, может использоваться в любом месте, где константа может
будет.
(C2011, 6,6 / 2)
Вы продолжаете разъяснять цель, для которой вы хотите использовать такое постоянное выражение:
С утверждением я хочу проверить случаи, когда такое усечение не
просто может произойти, но когда на самом деле делает .
Обратите внимание, однако, что
Для этой цели размер битового поля является вторичным. То, что вы на самом деле хотите, это максимальное представимое значение. Для битовых полей со знаковыми типами, может быть, вы тоже хотите минимум.
На самом деле вам не нужно постоянное выражение для использования в регулярном утверждении, таком как вы демонстрируете (в отличие от статического утверждения). Выражение в регулярном утверждении вычисляется во время выполнения.
С другой стороны, некоторые выражения, которые не удовлетворяют определению константного выражения в стандарте, могут все еще вычисляться во время перевода (компиляции) некоторыми реализациями.
Точки (2) и (3) удачны для вас, потому что битовые поля имеют типы второго класса, которые не могут быть выражены напрямую. Нет значений любого типа битового поля вне контекста объекта структуры хоста, и нет имени типа, с помощью которого можно выразить эффективный тип битового поля. И означает, что означает, что нет постоянного выражения, которое оценивает число бит или максимальное значение элемента битового поля, если только оно не включает в себя предварительное знание этого элемента, поскольку структуры (включая литералы структуры) не входят в число операндов. который может появиться в подходящем константном выражении:
Арифметическое константное выражение должно иметь арифметический тип и должно
иметь только операнды, которые являются целочисленными константами, плавающими константами,
константы перечисления, символьные константы, sizeof
выражения, чьи
Результатами являются целочисленные константы и выражения _Alignof
. В ролях
операторы в выражении арифметической константы должны преобразовывать только
арифметические типы для арифметических типов, кроме как часть операнда для
оператор sizeof
или _Alignof
.
( C2011 6,6 / 8 )
После всего этого, я думаю, вопрос действительно сводится к следующему:
Я не уверен, гарантированно ли это работает:
assert(someveal <= ((mystruct){.threebits = -1}).threebits);
Для неподписанных битовых полей, таких как mystruct.threebits
, он гарантированно будет работать в C99 или новее. Более ранние версии C не имеют составных литералов или назначенных инициализаторов, однако, и некоторые реализации C, с которыми вы можете столкнуться даже сегодня, не соответствуют C99. В такой реализации вы могли бы вместо этого просто определить (может быть const
, возможно static
) экземпляр вашей структуры, в которой можно записать ограничения ...
static const struct mystruct mystruct_limits = { -1, -1, -1 };
... а затем сравнить с его членами:
assert(someveal <= mystruct_limits.threebits);
Обратите внимание, что инициализаторы членов структуры подвергаются тем же преобразованиям, которые применяются при простом присваивании, поэтому, пока члены имеют неподписанные типы, значения -1 в качестве значений инициализатора хорошо определены, чтобы иметь желаемый эффект.
Обратите также внимание, что хотя const
является желательным для этой цели, он не был стандартизирован до C99. Однако до C99 это было довольно распространенное расширение, и вы с гораздо меньшей вероятностью столкнетесь с компилятором C, который отклоняет const
, чем с компилятором, который отклоняет составные литералы.