2014-09-13 17 views
10

Ich arbeite mit Strukturen in c auf Linux. Ich begann Bitfelder verwenden und die „verpackt“ -Attribut und stieß ich auf ein sonderbares Verhalten:Gepackte Bitfelder in c-Strukturen - 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 
} 

Wie beide Strukturen kommen -, die genau die gleichen sind - nehmen diffrent Anzahl von Bytes?

+1

Weil 't2 :: b 'garantiert ein eindeutiger Speicherort ist? Denken Sie an Datenrennen. –

Antwort

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

Die regelmäßigen int b muss eine Bytegrenze ausgerichtet werden. Es gibt also eine Polsterung davor. Wenn Sie c direkt neben a setzen, ist diese Aufpolsterung nicht mehr notwendig. Sie sollten dies wahrscheinlich tun, da der Zugriff auf Nicht-Byte-ausgerichtete Ganzzahlen wie int b:32 langsam ist.

16

Ihre Strukturen sind nicht "genau gleich". Ihre erste hat drei aufeinanderfolgende Bit-Felder, die zweite ein Bit-Feld, ein (nicht Bit-Feld) int und dann ein zweites Bit-Feld.

Dies ist von Bedeutung: aufeinander folgende (nicht Null Breite) Bitfelder zusammengeführt werden zu einem einzigen Speicherplatz, während ein Bit-Feld, das durch ein nicht-Bit-Feld gefolgt Orte unterschiedliche Speicher befinden.

Ihre erste Struktur hat einen einzigen Speicherort, Ihre zweite hat drei. Sie können die Adresse des Elements b in Ihrer zweiten Struktur nehmen, nicht in Ihrer ersten. Zugriffe auf das b Mitglied rennen nicht mit Zugriff auf die a oder c in Ihrer zweiten Struktur, aber sie tun in Ihrem ersten.

Wenn ein Nicht-Bitfeld (oder ein Nulllängen-Bitfeld) unmittelbar nach dem Schließen eines Bitfeldelements in einem Sens "schließt", folgt ein anderer/unabhängiger Speicherort/Objekt. Der Compiler kann Ihr b-Member nicht wie in der ersten Struktur in das Bitfeld "packen".