2012-07-19 4 views
26

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

+0

Вы уверены, что в теге смешанного режима? –

+2

Не C++ инициализирует 'union' первым элементом? То есть 'static const Y_CONSTANT = {{0,0,0,0}};' – YePhIcK

+0

@YePhIcK затем дает дополнительные предупреждения о пропавших брекетах. – Alex

ответ

15

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

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

Я нашел это объяснение по адресу: Initialization of structures and unions

3

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

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

    Foo() : raw{} { } 
}; 

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

+0

Я сомневаюсь, что конструктор будет обрабатываться компилятором C. – Alex

+1

@Alex: Нет, конечно нет. Но с удачей структура будет * layout-compatible * с аналогично объявленной структурой C ... –

+0

А я вижу, что вы хотите предложить использовать '#ifdef __cplusplus' в нужном месте, чтобы включить этот заголовочный файл. Ах, это может стать еще более нечетким. – Alex

1

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

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

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

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

2

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

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

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

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

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

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

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

+0

"* ANSI C99 *" ... – Spookbuster

+0

@Spookbuster https://en.wikipedia.org/wiki/ANSI_C#C99 да? – Alex

Смежные вопросы