打包位域更紧凑

时间:2012-07-25 09:36:35

标签: c++ inheritance g++ bit-fields packed

我在派生类中遇到了位域问题。

使用g ++编译器,您可以将__attribute__((packed))分配给一个类,它将打包位域。所以

class A
{
  public:
    int one:10;
    int two:10;
    int three:10;
} __attribute__ ((__packed__));

只占用4个字节。到目前为止,这么好 但是,如果你继承了一个类,就像这样

class B
{
  public:
    int one:10;
    int two:10;
} __attribute__ ((__packed__));

class C : public B
{
  public:
    int three:10;
} __attribute__ ((__packed__));

我希望C类与上面的A类具有相同的内容,同样具有相同的布局,即占用4个字节。但是,C结果占用了5个字节。

所以我的问题是,我做错了什么,如果是的话,那是什么?或者这是编译器的问题?疏忽,真正的错误?

我尝试使用谷歌搜索,但除了Linux和Windows(编译器试图模拟MSVC)之间的区别之外,我还没有真正想出任何东西,我对此并不感兴趣。这只是在Linux上。< / p>

2 个答案:

答案 0 :(得分:0)

我认为问题在于B,它不容易成为2.5个字节。它必须至少为3个字节。

理论上,派生类可能可以重用基类中的填充,但我从未见过这种情况。

答案 1 :(得分:0)

想象一下你要求 的可能性。可能出现的副作用或问题是什么?让我们看一下您所拥有的特定示例。还假设采用1字节内存对齐的32位架构。

class A中有20个连续位可以通过班级成员onetwo进行处理。对你来说,这是一个非常方便的解决方案。但编译器做了什么才能实现呢?它使用掩码和位移位将位置这些位置到正确的位置。

到目前为止,这么好,似乎简单而且足够安全。

再添加10位。假设有一些非常智能的编译器允许你将这些额外的10位压缩成一个已经使用过的32位字(它们非常适合,不是吗?)。

遇到麻烦:

A* derived = new B; // upcast to base class
derived->one = 1;
derived->two = 2;
// what is the value of derived->three in this context?
// Especially taking into account that a compiler is free to do all sorts
// of optimizations when generating code for class A

由于上述内容,class A成员和class B成员使用不同且可单独寻址的内存位置那些10位“溢出”到下一个可寻址存储器位置 - 下一个字节。

当您考虑多重继承时会出现更多麻烦 - 在派生类中排列位的一种真实方式是什么?