¿Cómo se determina / mide el tamaño de una estructura con Bit Fields?

#include  typedef struct size { unsigned int a:1; unsigned int b:31; unsigned int c:1; } mystruct; int main() { mystruct a; printf("%d", sizeof(a)); return 0; } 
  • Con int b:31 , la salida es 8.
  • Con int b:1 , la salida es 4.
  • Con int b:32 , la salida es 12.

¿Alguien puede explicar el motivo de esto?

No dices si sabes qué bitfields son, pero supongo que sí.

En su implementación, evidentemente unsigned int es un entero de 32 bits que ocupa 4 bytes. Esto explica el primer y el segundo ejemplo. Claramente, 3 campos de bit que sumn 33 bits no caben en un único unsigned int , de ahí la necesidad de 8 bytes en el primer ejemplo. 3 campos de bit que sumn 3 bits ciertamente encajan en un unsigned int , por lo tanto, solo 4 bytes en el segundo ejemplo.

Además, un campo de bits no puede abarcar múltiples enteros. Esto explica el tercer ejemplo. No puedo recordar si eso es un requisito del estándar, o solo un detalle de su implementación. De cualquier manera, dado que b es de 32 bits, llena un entero unsigned int por sí mismo, forzando tanto a como c a ocupar su propia unsigned int , antes y después de la del medio. Por lo tanto, 12 bytes.

Es el orden lo que importa. El siguiente código dará salida: 8

 #include typedef struct size { unsigned int b:32; unsigned int a:1; unsigned int c:1; }mystruct; int main(int argc, char const *argv[]) { mystruct a; printf("\n %lu \n",sizeof(a)); return 0; } 

Unsigned int es un entero de 32 bits que ocupa 4 bytes. La memoria se asigna contiguamente en la memoria.


Opción 1:

 unsigned int a:1; // First 4 bytes are allocated unsigned int b:31; // Will get accomodated in the First 4 bytes unsigned int c:1; // Second 4 bytes are allocated 

Salida: 8


Opcion 2:

 unsigned int a:1; // First 4 bytes are allocated unsigned int b:32; // Will NOT get accomodated in the First 4 bytes, Second 4 bytes are allocated unsigned int c:1; // Will NOT get accomodated in the Second 4 bytes, Third 4 bytes are allocated 

Salida: 12


Opción 3:

 unsigned int a:1; // First 4 bytes are allocated unsigned int b:1; // Will get accomodated in the First 4 bytes unsigned int c:1; // Will get accomodated in the First 4 bytes 

Salida: 4


Opción 4:

 unsigned int b:32; // First 4 bytes are allocated unsigned int a:1; // Second 4 bytes are allocated unsigned int c:1; // Will get accomodated in the Second 4 bytes 

Salida: 8

Alineación

El comstackdor redondea el tamaño de la estructura a 32 bits, el tamaño de cada objeto puede tratar de hacer referencia a 32 bits y, al mismo tiempo, conserva el orden de los campos de bits.

Entonces, si tiene un elemento de 32 bits en el medio y elementos de 1 bit en cada lado, son 3 palabras de 32 bits para asignar y así: 12 bytes.

Para los otros dos casos, solo se trata de la cantidad de objetos de 32 bits en los que se puede empaquetar su secuencia de campo de bits, conservando al mismo tiempo el orden de los campos.

De acuerdo con la respuesta de Steve Jessop solo para completar su respuesta agregando algunos documentos que pueden ayudar.

Un miembro de una estructura o unión puede tener cualquier tipo de objeto completo que no sea un tipo modificado de forma variable. Además, se puede declarar que un miembro consta de un número específico de bits (incluido un bit de signo, si lo hay). Tal miembro se denomina campo de bits, su ancho está precedido por dos puntos

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.

Dentro de un objeto de estructura, los miembros de campo que no son de bit y las unidades en que residen los campos de bit tienen direcciones que aumentan en el orden en que se declaran . Un puntero a un objeto de estructura, adecuadamente convertido, apunta a su miembro inicial (o si ese miembro es un campo de bits, luego a la unidad en la que reside), y viceversa. Puede haber un relleno sin nombre dentro de un objeto de estructura, pero no al principio.

–ISO / IEC 9899: 201x 6.7.2.1