18

重複の可能性:
長さゼロのビットフィールドの実用的な使用

一部の構造にゼロ幅のビットフィールドがあるのはなぜですか?また、なぜそれが必要なのですか?

struct foo {
  int    a:3;
  int    b:2;
  int     :0; // Force alignment to next boundary.
  int    c:4;
  int    d:3;
};

int main()
{
        int i = 0xFFFF;
        struct foo *f = (struct foo *)&i;
        printf("a=%d\nb=%d\nc=%d\nd=%d\n", f->a, f->b, f->c, f->d);
        return 0;
}

上記のプログラムの出力は次のとおりです。

manav@os-team:~/programs/test$ ./a.out
a=-1
b=-1
c=-8
d=0

これらの値が負である理由と、構造内のこれらの変数のメモリレイアウトについて説明してください。

4

4 に答える 4

12

Google検索でのこの最初のヒットから:

長さが0のビットフィールドには名前を付けないでください。名前のないビットフィールドは、参照または初期化できません。ゼロ幅のビットフィールドにより、次のフィールドが次のコンテナ境界に整列される可能性があります。この場合、コンテナは、ビットフィールドの基になるタイプと同じサイズです。

質問の2番目の部分については、構造体のビットフィールドの一部をすべて1に設定します。これらのフィールドは署名されているため、これらのフィールドの値は負になります。構造体全体を1に設定し、符号付き表現と符号なし表現の両方の値を確認すると、これをより効果的に確認できます。

int main()
{
    struct foo f;
    memset(&f, 0xff, sizeof(f));
    printf("a=%d\nb=%d\nc=%d\nd=%d\n", f.a, f.b, f.c, f.d); // print fields as signed
    printf("a=%u\nb=%u\nc=%u\nd=%u\n", f.a, f.b, f.c, f.d); // print fields as unsigned
    return 0;
}
于 2012-12-10T14:26:14.363 に答える
3

ここで述べたように、長さがゼロのビットフィールドはビットフィールド間の整列を追加します。行に複数のビットフィールドがある場合、それらのレイアウトはコンパクトですが、そのうちの1つをバイト/ワード/ dwordの境界に揃える場合は、これと前のビットフィールドの間に長さゼロのビットフィールドを配置する必要があります。

上記のリンクからの例:

struct on_off {
                  unsigned light : 1;
                  unsigned toaster : 1;
                  int count;            /* 4 bytes */
                  unsigned ac : 4;     // this and
                  unsigned : 4;        // this and
                  unsigned clock : 1;  // this bitfields are next to each other
                  unsigned : 0;
                  unsigned flag : 1;   // this bitfield is at a 4 bytes boundary.
                 } kitchen ;
于 2012-12-10T14:31:12.957 に答える
3

メモリレイアウトは「状況によって異なります」であり、特定のコンパイラからの特定のレイアウトを信頼することはできません。実際、設定を変更すると、特定のコンパイラとは異なるレイアウトが表示される場合があります。推測したり、直感したり、レイアウトに依存したりしないでください。

負-すべての要素はint符号付きであるため、すべてのビットを1に初期化したため負であり、符号ビットが設定されています。dに関しては-私を打ち負かします。打ち間違え?

于 2012-12-10T14:26:40.377 に答える
1

ビットフィールドが符号付きであるため、数値は負になります。つまり、signed char変数がある場合、そのサイズは8ビットであり、256の異なる値を保持できます。値の半分は正、残りは負、0です。最上位ビットは符号を示します(負の場合は1、正の場合は0)。ゼロ長ビットフィールドについては、ここを参照してください:ゼロ長ビットフィールドの実用的な使用

于 2012-12-10T14:27:14.357 に答える