2013-07-04 9 views
5

Rozważmy następujący:C++ Podbudowa Bitfield Rozmiar

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

kompilator g ++ 4.8.1. sizeof (A) == 1, sizeof (B) == 4. Dlaczego tak jest? Potrzebuję czegoś podobnego do struktury B, by mieć rozmiar 1.

+0

FWIW, wygląda dobrze z GCC 4.7.2: http://ideone.com/5UpazC (jest to z atrybutem zastosowanym bezpośrednio do wewnętrznej struktury). –

+1

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

+0

@OliCharlesworth Twój kod różni się od OP. Zobacz http://ideone.com/Z4wOkE – johnchen902

Odpowiedz

3

To może wydawać się głupie kontr-pytanie. I uzyskać wynik pragnienie kiedy przepisać swój przykład jako:

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

Czy jest jakiś powód, dla którego nie można ponownie definicję class A wewnątrz class B? To naprawdę wydaje się być lepszym sposobem na zrobienie tego.

Jak pamiętam, ani C ani C++ nie gwarantuje, że struct Sub będzie miał identyczny układ i ma identyczne wymagania co do przechowywania, jak class A, pomimo tego samego pola szerokości, kolejności i tak dalej. (W przypadku C, będzie to struct Sub w porównaniu do struct A, ale ten sam pomysł obowiązuje, ponieważ są to wszystkie typy POD.)

Dokładne zachowanie powinno być zależne od ABI. Przez ponowne użycie class A, tak jak powyżej, myślę, że jesteś nieco bardziej odporny na problemy ABI. (Nieco nieprzepuszczalny.)

+0

"ani C lub C++ gwarantuje ... "- nieco nieistotny, ponieważ' __attribute __ ((pakowany)) jest rozszerzeniem specyficznym dla kompilatora;) –

+0

Byłoby to dopuszczalne obejście, +1, chociaż dla pełnych punktów, chciałbym wiem _ dlaczego moja droga nie działa. Re ABI: to nieco bardziej skomplikowane - to _jest_ w kontekście _making_ an OS :-) – imallett

+0

A '__attribute__' to tylko niestandardowa wskazówka dla kompilatora. W przeciwnym razie powinno osłabić gwarancje standardu, z wyjątkiem przypadków, gdy wyraźnie takie gwarancje są bardziej rygorystyczne. W każdym przypadku użycie 'klasy A' bezpośrednio w' klasie B' daje pożądany efekt, przynajmniej pod ABI x86-64. –