3

派生クラスのビットフィールドに問題があります。

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

上記のクラス A と同じコンテンツを持つクラス C も同じレイアウト、つまり 4 バイトを占めると予想します。ただし、C は 5 バイトを占有することが判明しました。

だから私の質問は、私は何か間違ったことをしているのですか?それともコンパイラの問題ですか?見落とし、本当のバグ?

私はグーグルを試しましたが、興味のないLinuxとWindows(コンパイラがMSVCをエミュレートしようとする場所)の違いを除けば、実際には何も思いつきませんでした。これはLinux上だけです。

4

2 に答える 2

0

あなたが求めていること可能であると想像してみてください。その副作用や問題点は何ですか?あなたが持っている特定の例を見てみましょう。また、メモリ アライメントが 1 バイトの 32 ビット アーキテクチャを想定します。

クラスclass Aのメンバー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

上記の理由により、クラスのメンバーとのメンバーに対して、個別にアドレス指定可能な異なるメモリ ロケーションを使用する必要があります。これらの 10 ビットは、次のアドレス指定可能なメモリ ロケーション (次のバイト) に「流出」します。class Aclass B

多重継承を考慮すると、さらに問題が発生します。派生クラスでビットを配置する真の方法はどれですか?

于 2012-07-25T09:58:02.053 に答える
0

問題は B にあると思いますが、これは簡単には 2.5 バイトにはなりません。少なくとも 3 バイトである必要があります。

理論的には、派生クラスは基本クラスのパディングを再利用できるかもしれませんが、私はそれが起こるのを見たことがありません。

于 2012-07-25T09:45:39.460 に答える