2014-09-13 10 views
10

Sto lavorando con le strutture in c su linux. ho iniziato ad usare campi di bit e la "imballato" attributo e mi sono imbattuto in un comportamento strano:Campi di bit compressi in strutture c - GCC

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 
} 

Come mai entrambe le strutture - che sono esattamente lo stesso - prendere il numero differente di byte?

+1

Perché 't2 :: b' è garantito come una posizione di memoria distinta? Pensa alle gare di dati. –

risposta

10
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)); 

Il regolare int b deve essere allineato a un limite di byte. Quindi c'è il padding prima di esso. Se inserisci c proprio accanto a a, questo riempimento non sarà più necessario. Probabilmente dovresti farlo, poiché l'accesso a numeri interi non allineati a byte come int b:32 è lento.

16

Le tue strutture non sono "esattamente uguali". Il primo ha tre campi bit consecutivi, il secondo ha un campo-bit, un (non bit-field) int e quindi un secondo campo-bit.

Ciò è significativo: consecutive (non zero) larghezza bit-campi vengono uniti in un unico locazione di memoria, mentre un campo bit seguito da un non-campo bit sono posizioni di memoria distinte.

La tua prima struttura ha una singola posizione di memoria, la seconda ne ha tre. Puoi prendere l'indirizzo del membro b nella tua seconda struttura, non nel tuo primo. Gli accessi al membro b non corrono con gli accessi allo a o c nella seconda struttura, ma lo fanno nel primo.

Avendo un campo di bit non a bit (o un campo di bit a lunghezza zero) subito dopo che un membro di campo di bit "lo chiude" in un sens, ciò che segue sarà una posizione/oggetto di memoria diversa/indipendente. Il compilatore non può "comprimere" il membro b all'interno del campo di bit come fa nella prima struttura.