Campos de bits empaquetados en estructuras c – GCC

Estoy trabajando con estructuras en c en linux. Comencé a usar campos de bits y el atributo “empaquetado” y me encontré con un comportamiento extraño:

struct t1 { int a:12; int b:32; int c:4; }__attribute__((packed)); struct t2 { int a:12; int b; int c:4; }__attribute__((packed)); void main() { printf("%d\n",sizeof(t1)); //output - 6 printf("%d\n",sizeof(t2)); //output - 7 } 

¿Cómo es que ambas estructuras, que son exactamente iguales, toman un número diferente de bytes?

Tus estructuras no son “exactamente iguales”. El primero tiene tres campos de bits consecutivos, el segundo tiene un campo de bits, un int (sin campo de bits) y luego un segundo campo de bits.

Esto es significativo: los campos de bits consecutivos (de ancho diferente a cero) se combinan en una única ubicación de memoria , mientras que un campo de bits seguido de un campo que no es de bits son ubicaciones de memoria distintas.

Tu primera estructura tiene una sola ubicación de memoria, tu segunda tiene tres. Puede tomar la dirección del miembro b en su segunda estructura, no en su primera. Los accesos al miembro b no compiten con los accesos a o c en su segunda estructura, pero sí en la primera.

Al tener un campo que no es de bits (o un campo de bits de longitud cero) justo después de que un miembro del campo de bits lo “cierra” en un sentido, lo que sigue será una ubicación / objeto de memoria diferente / independiente. El comstackdor no puede “empaquetar” su miembro b dentro del campo de bits como lo hace en la primera estructura.

 struct t1 // 6 bytes { int a:12; // 0:11 int b:32; // 12:43 int c:4; // 44:47 }__attribute__((packed)); struct t1 // 7 bytes { int a:12; // 0:11 int b; // 16:47 int c:4; // 48:51 }__attribute__((packed)); 

El int b regular debe estar alineado con un límite de byte. Así que hay relleno delante de él. Si pones c justo al lado de este relleno ya no será necesario. Probablemente debería hacer esto, ya que acceder a enteros no alineados con bytes como int b:32 es lento.