sirve sintaxis que para estructuras estructura datos campos arreglo anidadas c++ c bit-manipulation endianness bit

que - sintaxis de c++



C/C++: orden y alineaciĆ³n del campo de bits de fuerza (6)

Leí que el orden de los campos de bit dentro de una estructura es específico de la plataforma. ¿Qué pasa si uso diferentes opciones de empaquetado específicas del compilador, estos datos de garantía se almacenarán en el orden correcto a medida que se escriben? Por ejemplo:

struct Message { unsigned int version : 3; unsigned int type : 1; unsigned int id : 5; unsigned int data : 6; } __attribute__ ((__packed__));

En un procesador Intel con el compilador GCC, los campos se presentaron en la memoria tal como se muestran. Message.version fue los primeros 3 bits en el buffer, y Message.type seguido. Si encuentro opciones de empaque de struct equivalentes para varios compiladores, ¿será multiplataforma?


Deben evitarse los Bitfields; no son muy portátiles entre los compiladores, incluso para la misma plataforma. del estándar C99 6.7.2.1/10 - "Especificadores de estructura y unión" (hay una redacción similar en el estándar C90):

Una implementación puede asignar cualquier unidad de almacenamiento direccionable lo suficientemente grande como para contener un campo de bits. Si queda suficiente espacio, un campo de bits que sigue inmediatamente a otro campo de bits en una estructura debe empaquetarse en los bits adyacentes de la misma unidad. Si queda espacio insuficiente, si un campo de bits que no encaja se coloca en la siguiente unidad o se solapa con las unidades adyacentes, se define la implementación. El orden de asignación de los campos de bits dentro de una unidad (de orden superior a orden inferior o de orden bajo a orden superior) está definido por la implementación. La alineación de la unidad de almacenamiento direccionable no está especificada.

No se puede garantizar si un campo de bit ''abarcará'' un límite int o no y no se puede especificar si un bitfield comienza en el extremo inferior del int o el extremo superior del int (esto es independiente de si el procesador es big-endian o little-endian).

Prefiero máscaras de bits. Use líneas en línea (o incluso macros) para configurar, borrar y probar los bits.


La mayoría de las veces, probablemente, pero no apueste a la granja, porque si se equivoca, perderá en grande.

Si realmente, realmente necesitas tener información binaria idéntica, necesitarás crear campos de bits con máscaras de bits, por ejemplo, usar un corto sin firmar (16 bit) para Mensaje, y luego hacer cosas como versionMask = 0xE000 para representar los tres bits más altos.

Hay un problema similar con la alineación dentro de las estructuras. Por ejemplo, las CPU Sparc, PowerPC y 680x0 son todas de gran tamaño, y el valor predeterminado común para los compiladores Sparc y PowerPC es alinear los miembros de la estructura en los límites de 4 bytes. Sin embargo, un compilador que utilicé para 680x0 solo se alineó en los límites de 2 bytes, ¡y no había ninguna opción para cambiar la alineación!

Entonces, para algunas estructuras, los tamaños en Sparc y PowerPC son idénticos, pero más pequeños en 680x0, y algunos de los miembros están en diferentes desplazamientos de memoria dentro de la estructura.

Esto fue un problema con un proyecto en el que trabajé, porque un proceso de servidor que se ejecuta en Sparc interrogaría a un cliente y descubriría que era un gran candidato, y supondría que podría lanzar estructuras binarias en la red y el cliente podría hacer frente. Y eso funcionó bien en los clientes de PowerPC y se estrelló a lo grande en clientes de 680x0. No escribí el código, y me tomó bastante tiempo encontrar el problema. Pero fue fácil de solucionar una vez que lo hice.


Los campos de bits varían mucho de compilador a compilador, lo siento.

Con GCC, las máquinas de Big Endian diseñan primero los bits grandes y las pequeñas máquinas endian establecen primero las partes pequeñas.

K & R dice "Los miembros adyacentes de las estructuras [bit-] field se empaquetan en unidades de almacenamiento dependientes de la implementación en una dirección que depende de la implementación. Cuando un campo que sigue a otro campo no cabe ... se puede dividir entre unidades o la unidad puede estar acolchado. Un campo sin nombre de ancho 0 fuerza este relleno ... "

Por lo tanto, si necesita un diseño binario independiente de la máquina, debe hacerlo usted mismo.

Esta última afirmación también se aplica a los campos que no son bit debido al relleno; sin embargo, todos los compiladores parecen tener algún modo de forzar el relleno de bytes de una estructura, como veo que ya descubrieron para GCC.


No, no será totalmente portátil. Las opciones de embalaje para estructuras son extensiones, y en sí mismas no son totalmente portátiles. Además de eso, C99 §6.7.2.1, párrafo 10 dice: "El orden de asignación de los campos de bits dentro de una unidad (de orden superior a bajo orden o de orden bajo a orden superior) está definido por la implementación."

Incluso un solo compilador puede colocar el campo de bits de forma diferente dependiendo de la endianidad de la plataforma de destino, por ejemplo.


Por supuesto, la mejor respuesta es usar una clase que lea / escriba los campos de bits como una secuencia. El uso de la estructura de campo de C bits simplemente no está garantizado. Sin mencionar que se considera poco profesional / flojo / estúpido usar esto en la codificación del mundo real.


endianness están hablando de órdenes de bytes y no de órdenes de bits. Hoy en día , es 99% seguro de que los pedidos de bits son fijos. Sin embargo, al usar bitfields, la endianidad se debe tomar en cuenta. Vea el ejemplo a continuación.

#include <stdio.h> typedef struct tagT{ int a:4; int b:4; int c:8; int d:16; }T; int main() { char data[]={0x12,0x34,0x56,0x78}; T *t = (T*)data; printf("a =0x%x/n" ,t->a); printf("b =0x%x/n" ,t->b); printf("c =0x%x/n" ,t->c); printf("d =0x%x/n" ,t->d); return 0; } //- big endian : mips24k-linux-gcc (GCC) 4.2.3 - big endian a =0x1 b =0x2 c =0x34 d =0x5678 // - little endian : gcc (Ubuntu 4.3.2-1ubuntu11) 4.3.2 a =0x2 b =0x1 c =0x34 d =0x7856