2013-07-04 23 views
5

Si consideri il seguente:C++ sottostruttura bitfield Dimensioni

class A { public: 
    int  gate_type : 4; 
    bool storage_elem : 1; 
    uint8_t privilege : 2; 
    bool  present : 1; 
} __attribute__((packed)); 

class B { public: 
    struct Sub { 
     int  gate_type : 4; 
     bool storage_elem : 1; 
     uint8_t privilege : 2; 
     bool  present : 1; 
    } type_attr; //Also tried with "__attribute__((packed))" here in addition to outside 
} __attribute__((packed)); 

compilatore g ++ è 4.8.1. sizeof (A) == 1, sizeof (B) == 4. Perché è così? Ho bisogno di qualcosa come la struttura B per avere la dimensione 1.

+0

FWIW, sembra ok con GCC 4.7.2: http://ideone.com/5UpazC (questo è con l'attributo applicato direttamente alla struttura interna). –

+1

http://coliru.stacked-crooked.com/view?id=93e976a41246e1de4cdae7418040122e-f674c1a6d04c632b71a62362c0ccfc51 –

+0

@OliCharlesworth Il tuo codice è diverso da OP. Vedi http://ideone.com/Z4wOkE – johnchen902

risposta

3

Questa può sembrare una stupida contro-domanda. Ottengo il risultato desiderato quando riscrivo il vostro esempio come:

class A { public: 
    int  gate_type : 4; 
    bool storage_elem : 1; 
    uint8_t privilege : 2; 
    bool  present : 1; 
} __attribute__((packed)); 

class B { public: 
    A type_attr; //Also tried with "__attribute__((packed))" here in addition to outside 
}; 

C'è qualche motivo non è possibile riutilizzare la definizione di class A all'interno di class B? Questo sembra essere il modo migliore per farlo.

Come ricordo, né C né C++ garantiscono che lo struct Sub abbia un layout identico e abbia requisiti di archiviazione identici a class A, nonostante abbia le stesse larghezze di campo, ordine e così via. (Nel caso di C, sarebbe struct Sub rispetto a struct A, ma la stessa idea vale, poiché questi sono tutti i tipi di POD.)

Il comportamento esatto dovrebbe essere dipendente dall'ABI. Riutilizzando lo class A come ho fatto in precedenza, penso che ti renderai leggermente più immune ai problemi dell'ABI. (Leggermente, non impervio.)

+0

"né C o C++ garantiscono ... "- un po 'irrilevante, come' __attribute __ ((packed)) 'è un'estensione specifica del compilatore;) –

+0

Questa sarebbe una soluzione accettabile, +1, anche se per i punti completi, mi piacerebbe so perché ... il mio modo non funzionava. Re ABI: è leggermente più complicato - questo è nel contesto di _making_ un SO :-) – imallett

+0

E '__attribute__' è solo un suggerimento non standard per il compilatore. Se mai, dovrebbe indebolire le garanzie fatte dallo standard, tranne quando esplicitamente rende più severe tali garanzie. In ogni caso, l'uso di 'classe A' direttamente in' classe B' ottiene l'effetto desiderato, almeno sotto l'ABI x86-64. –