Инициализация объединения в C++ и C

Я построил рабочую библиотеку 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++.

4 ответов


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

с инициализаторами в стиле C89 элементы структуры должны быть инициализированы в порядок объявлен, и только первый член Союза может быть инициализировано

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


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

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

    Foo() : raw{} { }
};

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


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

  • Не используйте .member инициализации.
  • do nost use static const struct Foobar инициализация членов

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

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

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

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

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


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

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

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