Разрешена ли агрегированная инициализация битовых полей?

У меня есть структура, содержащая битовые поля:

struct Foo {
    unsigned a : 16, b : 16;
};

И я хочу знать, могу ли я использовать агрегированную инициализацию для его битовых полей. Например:

struct Foo bar = {13, 42};

Я отмечаю, что этот действительно работает в gcc 5.1 и Visual Studio 2015. Я просто хотел бы подтвердить, что это стандарт одобренная инициализация как для C, так и для C ++.


person Jonathan Mee    schedule 18.01.2016    source источник
comment
C и C ++ - разные языки. Выбери один.   -  person too honest for this site    schedule 18.01.2016
comment
@Olaf У меня есть библиотека, которая используется как C, так и C ++. Так что я не могу выбрать ни одного, и, конечно, хотел бы, чтобы ответ был одинаковым для обоих. Кстати, gcc отлично работает для обоих, вот аналог C моего примера в вопросе: ideone.com/a3iVXw   -  person Jonathan Mee    schedule 18.01.2016
comment
@JonathanMee: У меня есть библиотека - используйте язык, на котором скомпилирована библиотека. Семантика для C и C ++ иногда немного отличается. См. Один из моих комментариев выше. На самом деле битовые поля в Си мало используются. Если вам нужно (не) упаковать поля в целочисленный тип, просто используйте битовые поля; хороший компилятор сгенерирует почти такой же код, но вы получите конкретный макет. А использование битовых полей с размером, зависящим от реализации, всегда плохая идея.   -  person too honest for this site    schedule 18.01.2016
comment
@Olaf Я говорю, что код, который я пишу, будет использоваться как библиотека в двух отдельных проектах. Один из них - C ++, а другой - C. Если мне нужно вставить #ifdefs, я могу, но, похоже, в этом случае нет необходимости.   -  person Jonathan Mee    schedule 18.01.2016
comment
Написание библиотеки на довольно небольшом распространенном подмножестве C и C ++ звучит как плохой подход. В любом случае: ваш проект, ваша проблема.   -  person too honest for this site    schedule 18.01.2016


Ответы (1)


Из C ++ 14 [dcl.init.aggr] у нас есть

Агрегат - это массив или класс (раздел 9) без конструкторов, предоставленных пользователем (12.1), без частных или защищенных нестатических элементов данных (раздел 11), без базовых классов (раздел 10) и без виртуальных функций (10.3). ).

Итак, Foo является агрегатом и подходит для агрегатной инициализации. Тогда у нас есть

Когда агрегат инициализируется списком инициализаторов, как указано в 8.5.4, элементы списка инициализаторов принимаются в качестве инициализаторов для членов агрегата в возрастающем порядке индекса или члена. [...]

и

Статические элементы данных и анонимные битовые поля не считаются членами класса для целей агрегированной инициализации.

Таким образом, в вашем случае они будут инициализированы, поскольку они не анонимны, и они будут инициализированы в том порядке, в котором они появляются в struct.

Из C11 6.2.5 (21) имеем

Арифметические типы и типы указателей вместе называются скалярными типами. Типы массивов и структур вместе называются агрегатными типами. 46)

Итак, в C мы все еще имеем дело с агрегатом. Тогда в 6.7.9 (9) имеем

За исключением случаев, когда явно указано иное, для целей этого подпункта безымянные члены объектов структуры и типа объединения не участвуют в инициализации. Безымянные члены объектов структуры имеют неопределенное значение даже после инициализации.

и 6.7.9 (17)

Каждый список инициализаторов, заключенный в фигурные скобки, имеет связанный текущий объект. Если обозначений нет, подобъекты текущего объекта инициализируются в порядке, соответствующем типу текущего объекта: элементы массива в порядке возрастания индекса, элементы структуры в порядке объявления и первый именованный член объединения. 148 ) Напротив, обозначение заставляет следующий инициализатор начать инициализацию подобъекта, описанного указателем. Затем инициализация продолжается по порядку, начиная со следующего подобъекта после того, что описано обозначением. 149)

Таким образом, мы имеем то же поведение, что и в C ++, где анонимные битовые поля не инициализируются, но, поскольку они названы, они будут инициализированы в том порядке, в котором они появляются в struct.

person NathanOliver    schedule 18.01.2016
comment
Ответ неполный. Вопрос в тахеде C и C ++. - person too honest for this site; 18.01.2016
comment
@Olaf Я обновил ответ частью C. Я работал над сбором соответствующих стандартов, и мой стандартный pdf-файл на C немного сложнее искать, чем на моем C ++. - person NathanOliver; 18.01.2016
comment
Всегда лучше давать ссылки на стандарт: port70.net/~nsz/c /c11/n1570.html. - person too honest for this site; 18.01.2016
comment
@Olaf Если вы хотите быть разборчивым, то нет возможности предоставить ссылки на стандарты, поскольку они не являются общедоступными. (Однако, по крайней мере, C11 почти идентичен черновику. Единственное различие, которое я обнаружил, заключается в том, что официальный стандарт поставляется с Кор 1: 2012.) - person Lundin; 18.01.2016
comment
@Lundin: Хотя технически вы правы, как вы упомянули, нет существенной разницы между черновиком и фактическим стандартом. Фактически, клетки были ожидаемыми; Мне просто интересно, почему они фигурируют в исправлении, а не в самом окончательном стандарте. В любом случае, эта ссылка была в основном для того, чтобы упростить поиск и связать версию, поскольку Натан Оливер упоминает, что у него есть только PDF-файл. Очень жаль, что стандарт, оплачиваемый государственными деньгами (по крайней мере, немецкий DIN), по-прежнему стоит (довольно больших) денег. - person too honest for this site; 18.01.2016