2013-07-04 12 views
5

は、次のことを考えてみましょう:C++部分構造ビットフィールドサイズ

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

コンパイラがg ++ 4.8.1です。 sizeof(A)== 1、sizeof(B)== 4。なぜこれはそうですか?構造Bのようなサイズ1が必要です。

+0

GCC 4.7.2:http://ideone.com/5UpazC(これは属性が内部構造体に直接適用されています)ではFWIWと表示されます。 –

+1

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

+0

@OliCharlesworthあなたのコードはOPとは異なります。 http://ideone.com/Z4wOkE – johnchen902

答えて

3

これは疑問のようなカウンターのようです。

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

あなたがclass Bの内側class Aの定義を再利用することはできませんいくつかの理由がある:私のようにあなたの例を書き換えるとき、私はあなたが望む結果を得ますか?これは本当にそれを行う良い方法と思われます。

CとC++は、struct Subが同じフィールド幅、順序などを持っているにもかかわらず、同一のレイアウトを持ち、同一のストレージ要件をとすることを保証していません。 (Cの場合、struct Substruct Aですが、これらはすべてPODタイプなので同じ考えが成り立ちます)。

正確な動作はABI依存でなければなりません。私が上記のようにclass Aを再利用することによって、あなたはABIの問題を少しでも免れることができると思います。 (やや不透明ではない)

+0

"どちらもCやC++の保証... " - __attribute __((packed))はコンパイラ固有の拡張であるため、やや無関係です) –

+0

これは許容可能な回避策です。 _why_私のやり方はうまくいきませんでした。 Re ABI:それはちょっと複雑です - これは_making_の文脈でです_- – imallett

+0

そして '__attribute__'はコンパイラにとっては標準的でないヒントです。何かがあれば、明示的にそのような保証を厳しくする場合を除いて、規格によって保証される保証を弱めるはずです。 いずれにしても、 'class B'で直接' class A 'を使うことは、少なくともx86-64 ABIの下で、望ましい効果を得ます。 –