Вопрос по initialization, c++03, c, c++, unions – Объединение инициализации в C ++ и C

26

Я создал рабочую библиотеку C, которая использует константы, в заголовочных файлах, определенных как

typedef struct Y {
  union {
    struct bit_field bits;
    uint8_t raw[4];
  } X;
} CardInfo;

static const CardInfo Y_CONSTANT = { .raw = {0, 0, 0, 0 } };

Я знаю что.raw инициализатор - только синтаксис C

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

@YePhIcK тогда он дает дополнительные предупреждения о пропавших скобках. Alex
@YePhIcK Хорошо, фигурные скобки, кажется, делают свое дело, если вы используете правильное их количество и правильный порядок, но это ограничивает меня только возможностью инициализировать ОДИН выбор выбора объединения. никогда не позволяя мне инициировать второй. Alex
Не инициализируется ли C ++unionс первым элементом? То естьstatic const Y_CONSTANT = {{0,0,0,0}}; YePhIcK
Вы уверены в теге смешанного режима? Sebastian Mach
@Alex - Я только что попробовал свой код, и он прекрасно работал без ошибок / предупреждений. Вы уверены, что используете двойные скобки? typedef struct Y {union {struct bit_field bits; uint8_t raw [4]; } ИКС; } CardInfo; статическая константа CardInfo Y_CONSTANT = {{0, 0, 0, 0}}; YePhIcK

Ваш Ответ

4   ответа
15

У меня такая же проблема. Для C89 верно следующее:

With C89-style initializers, structure members must be initialized in the order declared, and only the first member of a union can be initialized

Я нашел это объяснение на: Инициализация структур и союзов

2

Я решил выбрать следующий путь.

Do not use .member initialization. do nost use static const struct Foobar initialization of members

Вместо этого объявите глобальную переменную:

extern "C" {
  extern const struct Foobar foobar;
}

и инициализировать его в глобальном разделе:

struct Foobar foobar = { 0, 0, 0, 0 };

и вместо того, чтобы глючить компилятор C ++ с современным синтаксисом ANSI C99, я позволил компоновщику выполнить работу по разборке символов C.

& Quot;ANSI C99& Quot; ...
@Spookbusteren.wikipedia.org/wiki/ANSI_C#C99 да? Alex
3

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

union Foo
{
    X x;
    uint8_t raw[sizeof(X)];

    Foo() : raw{} { }
};

Это по умолчанию инициализирует объединение типаFoo с активным участникомraw, который имеет все элементы с нулевой инициализацией. (До C ++ 11 не было возможности инициализировать массивы, которые не являются законченными объектами.)

@Offirmo C ++ 11 ввел новый терминstandard-layout class им разрешено иметь конструкторы; и во многих случаях, которые требовали POD в C ++ 03, теперь требуется только стандартный макет. (POD теперь определяется как стандартная схема плюс некоторые другие гарантии).
Ах, я вижу, поэтому вы хотите предложить использовать#ifdef __cplusplus в нужных местах, чтобы сделать этот заголовочный файл включаемым. Ах, это может стать еще более размытым. Alex
Предупреждение: добавление конструктора удаляет PODness, что часто желательно при работе с объединениями для доступа к памяти.
Я сомневаюсь, что конструктор будет разбираться компилятором C .. Alex
@ Алекс: Нет, конечно нет. Но если повезет, структура будетlayout-compatible с аналогично объявленной структурой C ...
1

C89 допускает инициализацию союзов, напрямую перечисляя элемент, который вы хотите инициализировать (например, что у вас есть в вашем коде). C99 изменил это так, чтобы вы могли инициировать объединение по его первому элементу.

C ++ допускает только эту форму инициализации - первым элементом. Вот код, который должен работать в любом случае:

static const CardInfo Y_CONSTANT = {{0, 0, 0, 0 } };
У вас есть это задом наперед. C89 / C90 позволяет инициализировать только первый элемент. C99 сохраняет ту же функцию (чтобы не нарушать существующий код), но добавляет назначенные инициализаторы. Ваше объявление не является допустимым C ++, если {0, 0, 0, 0} не является допустимым инициализатором для типаstruct bit_field.

Похожие вопросы