type fields c bit-fields

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



bit fields c (4)

#include <stdio.h> 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 la razón de esto?


Alineación

El compilador está redondeando el tamaño de la estructura a 32 bits, el tamaño de cada objeto al que puede intentar referirse a 32 bits y al mismo tiempo preserva el orden de sus 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, es solo una cuestión de la cantidad de objetos de 32 bits en los que se puede empaquetar su secuencia de campo de bits, mientras se conserva 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 corresponde). 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 no queda espacio suficiente, si un campo de bits que no se ajusta se coloca en la siguiente unidad o se superpone a las unidades adyacentes se define por la implementación. El orden de asignación de los campos de bits dentro de una unidad (orden alto a orden bajo o orden bajo a orden alto) 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 sin campo de bits y las unidades en las que residen los campos de bits 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


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

#include<stdio.h> 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


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 bits que suman 33 bits no caben en un solo unsigned int , de ahí la necesidad de 8 bytes en el primer ejemplo. 3 campos de bit que suman 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 unsigned int completo por sí mismo, lo que obliga a c a ocupar su propio unsigned int , antes y después del intermedio. Por lo tanto, 12 bytes.