Para algunos compiladores, hay un embalaje especificador de estructuras, por ejemplo:

RealView BRAZO compilador tiene "__embalado" 
Compilador de C de Gnu ha "__attribute__ ((__embalado__))" 
Visual C++ no tiene equivalente, sólo tiene el "#pragma pack(1)" 

Necesito algo que me puede poner en la struct definición.

Cualquier info/hack/sugerencia ? TIA…

  • Quiero el pack de toda la estructura. @Los demás: quiero tener un #define (en realidad 2) para realizar esta para compiladores que voy a utilizar. #pragma truco no funciona en algunos de ellos.
  • Tenga en cuenta que gcc ha apoyado #pragma pack desde al menos la versión 4.0; no está seguro acerca de RealView BRAZO.
InformationsquelleAutor Malkocoglu | 2009-10-08

6 Comentarios

  1. 28

    No sé una mancha de la manera de hacerlo, pero se podría hacer algo tan terrible como esto:

    #include "packed.h"
    struct Foo { /* members go here */ } PACKED;
    #include "endpacked.h"

    A continuación, para MSVC, lleno de.h:

    #define PACKED
    #pragma pack(push,1)

    endpacked.h

    #pragma pack(pop)
    #undef PACKED

    Para gcc, lleno de.h:

    #define PACKED __attribute__ ((__packed__))

    endpacked.h:

    #undef PACKED

    Fundamentalmente, el embalaje es demasiado dependiente de la plataforma. Supongamos que el empaque de tu estructura es de 8 bits de los campos, y considerar algunos con un sistema de 16 bits byte. No puede tener una estructura que representa los datos sólo por embalaje – tendrías que saber cómo de 8 bits, bytes son convertidos a 16 bits, bytes cuando se transfieren entre los dos sistemas. La estructura en la 16 bits de la máquina puede ser que necesite campos de bits, en cuyo caso tendrías que saber cómo la aplicación dispone.

    Así que si el código está destinado a ser generalmente portátil, usted sólo tiene que definir lo que sea lleno de estructuras que usted necesita en una plataforma específica de la sección de encabezado de archivo. O más bien, la estructura de su código para que un futuro puerto puede hacer eso si tiene que ser así.

    • Técnicamente, se podría hacer todo eso en un encabezado: #ifndef PACKED / #define PACKED / #else /* !PACKED */ / #undef PACKED / #endif /* PACKED */ y, a continuación, incluir una cabecera dos veces, una vez para activar y de una vez para desactivar. La utilidad / limpieza / cordura de tal práctica es discutible, pero así es la práctica que se sugiere.
    • Creo que voy a tomar «begin/end debe coincidir», más «se debe hacer un número par de veces», gracias ;-). Como dije en la respuesta, en principio, usted necesita una plataforma específica de la estructura de la definición. En la práctica, sin embargo, cubre los tres compiladores el interrogador actualmente preocupa, que permite más común que una gran cantidad de copiar/pegar, y no de forma espectacular horrible en comparación con un enjambre de #if _WIN32 #elif __GNUC__ y así sucesivamente alrededor de cada struct definición. #include es la correcta/única manera en C para abstracto o reutilización de un fragmento de código que contiene las directivas de preprocesador.
  2. 72

    Puede definir PACK como este para GNU gcc

    #define PACK( __Declaration__ ) __Declaration__ __attribute__((__packed__))

    y como este para Visual C++:

    #define PACK( __Declaration__ ) __pragma( pack(push, 1) ) __Declaration__ __pragma( pack(pop) )

    Y utilizarlo como este:

    PACK(
    struct myStruct
    {
        int a;
        int b;
    });
    • Yo era originalmente pensando que esto no funciona para typedef d structs, pero es posible que si typedef PACK(struct { int a; }) foo;. Creo que dependería de la #pragma/__pragma sintaxis del compilador en cuestión. Sin embargo, no funciona para las enumeraciones, ya que son internamente separados con comas (sí, las enumeraciones pueden ser empacados y a veces de la forma más limpia para resolver el problema).
    • Este enfoque fue utilizado por Symbian para todos estos atributos, como el blanco de un montón de compiladores y algunos querían que el compilador específico de bits por escrito antes de un identificador, otros después, etc.
    • Me gusta esta solución, sin embargo, me tomó mucho tiempo para averiguar que MSVC++ maneja los campos de bits de manera un poco diferente de GCC. Yo estaba usando «int» campos de bits de diferentes tamaños (1, 7, 8, 16) y descubrió que MSVC++ todavía quería a empacar todo en 4 bytes límites. Mediante la conversión a char de 1,7 y 8 de corto y de 16 luego me puse el embalaje que yo estaba esperando.
    • lo anterior funciona para typedefs si usted escribe PACK(typedef struct { int x; }) MyStruct;. También usted puede ser capaz de utilizar #define PACK(...) __VA_ARGS__ __attribute__((__packed__)) etc para manejar comas en la declaración cuerpo.
  3. 15

    Sé que esta pregunta es viejo ahora, pero creo que hay una mejor solución que los publicados anteriormente. Es posible poner el pragma en el MSVC caso en la declaración struct línea, después de todo. Considere lo siguiente:

    #ifdef _MSC_VER
    #  define PACKED_STRUCT(name) \
        __pragma(pack(push, 1)) struct name __pragma(pack(pop))
    #elif defined(__GNUC__)
    #  define PACKED_STRUCT(name) struct __attribute__((packed)) name
    #endif

    Entonces esto puede ser utilizado como:

    typedef PACKED_STRUCT() { short a; int b } my_struct_t;
    PACKED_SRUCT(my_other_struct) { short a; int b };

    etc.

    La clave aquí es que el uso de la __pragma sólo necesita estar cerca de la línea de declaración de la estructura. Esto debe incluir la estructura struct nombre si se da uno, de ahí el nombre de un parámetro de la macro. Por supuesto, esto es fácil de extender enum/clase, que te dejo como ejercicio para el lector!

    El programa de prueba en el paquete de documentación de la página de MSDN es útil para comprobar esto.

    EDITAR

    Resulta que en mis pruebas de que estaba usando el Compilador de Intel en Windows. El uso de icl.exe este enfoque funciona sin problema, pero con el compilador de Microsoft (cl.exe), no (probado con 2010 y 2013).

    • Me encantaría si esta realmente trabajado, como sería mantener la macro rareza se limita a la apertura de la línea de la estructura de la definición, pero cuando he intentado esto en MSVS 2010 con C++, tengo error C2143: syntax error : missing ';' before '{'. Tuve que volver a algo parecido a Steph del post, donde todo el cuerpo de la estructura de la definición es la macro argumento, que tipo de mierda. Sobre todo desde que se confunde vim contexto para colorear en C archivos (vim maneja bien con archivos de C++, aunque; no sé por qué).
    • No no trabajo bajo MSVC 2015 sea.
    • Sin embargo, el PACKED_STRUCT como una palabra clave es genial. Se puede combinar con Steph la solución de este tipo: #ifdef _MSC_VER # define PACKED_STRUCT( __Declaration__ ) __pragma( pack(push, 1) ) struct __Declaration__ __pragma( pack(pop) ) #elif defined(__GNUC__) # define PACKED_STRUCT( __Declaration__ ) struct __Declaration__ __attribute__((__packed__)) #endif Editado: bloques de código no se representan como se esperaba. Lo siento.
  4. 8

    Que usted puede hacer al revés, ya GCC apoya el VC++ pack relacionados con pragmas. Buscar aquí para obtener más información.

    Extraer…

    Para la compatibilidad con Microsoft Windows compiladores GCC admite un conjunto
    de #pragma directivas que cambiar el número máximo de alineación de los miembros de
    estructuras (distinto de cero-el ancho de los campos de bits), los sindicatos y las clases
    posteriormente se define. El valor de n a continuación siempre que se requiere para ser un
    de pequeña potencia de dos y especifica la nueva alineación de bytes.

    #pragma pack(n) simplemente establece la nueva alineación.

    #pragma pack() establece la alineación a la que estaba en vigor cuando
    compilación de introducción (vea también la opción de línea de comandos
    -fpack-struct[=<n>] ver el Código de Generación de Opciones).

    #pragma pack(push[,n]) empuja a la actual configuración de alineación en un
    interna de la pila y, a continuación, opcionalmente se establece la nueva alineación.

    #pragma pack(pop) restaura la configuración de alineación a la que uno guarda en
    la parte superior de la pila interna (y lo elimina de la pila de entrada).

    Nota que #pragma pack([n]) no influye en esta pila interna;
    por lo tanto es posible tener #pragma pack(push) seguido por varios
    #pragma pack(n) instancias y finalizado por un solo #pragma pack(pop).

    Algunos de los objetivos, por ejemplo, i386 y powerpc, de apoyo a la ms_struct #pragma
    el cual establece una estructura como la documentada __attribute__((ms_struct)).

    #pragma ms_struct on activa en el diseño de las estructuras, declaró.

    #pragma ms_struct off apaga el diseño de estructuras declarado.

    #pragma ms_struct reset vuelve a la configuración por defecto.

  5. 6

    Otra solución, en función de lo que los compiladores necesita apoyo, es un aviso de que GCC ha apoyado el Microsoft-estilo de embalaje pragmas, al menos desde la versión 4.0.4 (la documentación en línea está disponible en gnu.org para las versiones 3.4.6 y 4.0.4 – los pragmas no se describen en el antiguo y en el segundo caso). Esto permite que usted sólo tiene que utilizar #pragma pack(push,1) antes de una definición de la estructura y #pragma pack(pop) después de la definición y se compilará en cualquiera de los dos.

    • Confirmado que funciona, pero en mi humilde opinión @Steph la solución es mucho más elegante que poner pares de #pragma antes y después de cada declaración.
  6. 2

    Qué necesitas algo para ir en la estructura?

    Creo #pragma pack(1) es el mismo, o me estoy perdiendo algo?

    Usted puede hacer esto:

    struct Foo
    {
    #pragma pack(push, 1)
    int Bar;
    #pragma pack(pop)
    };

    Pero se ve feo.

    • Es realmente #pragma pack(push, 1) y #pragma pack(pop).

Dejar respuesta

Please enter your comment!
Please enter your name here