2012-07-19 34 views
26

he construido una biblioteca de trabajo C, que utiliza constantes, en los archivos de cabecera definido comoinicialización Unión en C++ y 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 } }; 

Sé que el .raw inicializador es C única sintaxis.

¿Cómo puedo definir las constantes con uniones en ellas de forma que pueda usarlas en C y C++?

+0

¿Estás seguro de la etiqueta de modo mixto? –

+2

¿C++ no está inicializando 'union's con el primer elemento? Es decir. 'static const Y_CONSTANT = {{0,0,0,0}};' – YePhIcK

+0

@YePhIcK luego da advertencias adicionales sobre llaves faltantes. – Alex

Respuesta

15

Tuve el mismo problema. Por C89 se cumple lo siguiente:

Con inicializadores de estilo C89, miembros de la estructura debe ser inicializado en el fin declarado, y sólo el primer miembro de un sindicato puede ser inicializado

encontré esta explicación en: Initialization of structures and unions

3

creo que C++ 11 permite que usted escriba su propio constructor de este modo:

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

    Foo() : raw{} { } 
}; 

Esta default-inicializa una unión de tipo Foo con raw miembro activo, que tiene todos los elementos inicializado a cero. (Antes de C++ 11, no había forma de inicializar matrices que no son objetos completos.)

+0

Dudo que un constructor sea parseable por un compilador C. – Alex

+1

@Alex: No, por supuesto que no. Pero con suerte, la estructura será * compatible con el diseño * con una estructura en C declarada de manera similar ... –

+0

Ah, veo, así que quieres sugerir el uso de '#ifdef __cplusplus' en los lugares correctos para poder incluir ese archivo de encabezado. Ah, eso podría ser aún más borroso. – Alex

1

C89 permitió la inicialización de uniones al listar directamente el elemento que desea iniciar (como el que tiene en su código). C99 ha cambiado eso para que pueda iniciar una unión por su primer elemento.

C++ solo permite esta forma de inicialización - por el primer elemento. Así que este es el código que debería funcionar bien para cualquier caso:

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

Lo tienes al revés. C89/C90 solo permite inicializar el primer miembro. C99 mantiene la misma característica (para evitar romper el código existente) pero agrega los inicializadores designados. Su declaración no es válida C++ a menos que {0, 0, 0, 0} sea un inicializador válido para el tipo 'struct bit_field'. –

2

Decidí elegir la siguiente ruta.

  • No utilice .member inicialización.
  • hacer uso nost static const struct Foobar inicialización de los miembros

declaran su lugar, la variable global:

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

e inicializar en una sección global:

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

y en vez de molestando el C++ compilador con sintaxis ANSI C99 moderna dejo que el enlazador haga el trabajo exigiendo símbolos C.

+0

"* ANSI C99 *" ... – Spookbuster

+0

@Spookbuster https://en.wikipedia.org/wiki/ANSI_C#C99 ¿sí? – Alex