2013-07-04 47 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

FWIW,它看起来OK GCC 4.7.2:http://ideone.com/5UpazC(这是与直接应用于内部结构的属性)。 –

+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 Subclass A具有相同的布局并具有相同的存储要求,尽管它们具有相同的字段宽度,顺序等等。 (在C的情况下,它应该是struct Substruct A,但同样的想法成立,因为这些都是POD类型。)

确切的行为应该是ABI依赖的。尽管如此,通过重复使用class A,我认为您可以让自己对ABI问题稍微有点免疫。 (稍微,不透水。)

+0

“既不是C和C++保证......“ - 与__attribute __((packed))是一个特定于编译器的扩展有些不相干;) –

+0

这是一个可以接受的解决方法,+1,尽管对于满分,我想知道_Why_我的方式不起作用。 Re ABI:它稍微复杂一点 - 这是在制作操作系统的环境中:-) – imallett

+0

而'__attribute__'只是编译器的一个非标准提示。如果有的话,它应该削弱标准所做出的保证,除非明确地使这种保证更加紧密。 在任何情况下,至少在x86-64 ABI下,直接在'class B'中使用'class A'可以获得理想的效果。 –