web-dev-qa-db-ja.com

ビットフィールドのある構造体のサイズはどのように決定/測定されますか?

#include <stdio.h>

typedef struct size
{
        unsigned int a:1;
        unsigned int b:31;
        unsigned int c:1;
} mystruct;

int main()
{
        mystruct a;
        printf("%d", sizeof(a));
        return 0;
}
  • int b:31、出力は8です。
  • int b:1、出力は4です。
  • int b:32、出力は12です。

誰かがこの理由を説明できますか?

38
Jagan

あなたはビットフィールドが何であるかを知っているかどうかは言いませんが、私はあなたが知っていると仮定します。

実装では、明らかにunsigned intは32ビット整数であり、4バイトを占めています。これは、最初と2番目の例の説明です。明らかに、合計33ビットの3つのビットフィールドは単一のunsigned intに適合しないため、最初の例では8バイトが必要です。合計3ビットの3ビットフィールドは確かにunsigned intに収まるため、2番目の例では4バイトのみです。

さらに、ビットフィールドは複数の整数にまたがることはできません。これが3番目の例です。それが標準の要件なのか、実装の詳細なのかを思い出せません。どちらの方法でも、bは32ビットであるため、unsigned int全体を単独で埋め、acの両方が、中央のunsigned intの前と後を強制的に占有します。したがって、12バイトです。

29
Steve Jessop

重要なのは順序です。次のコードは出力を提供します:8

#include<stdio.h>

typedef struct size
{
        unsigned int b:32;
        unsigned int a:1;
        unsigned int c:1;
}mystruct;

int main(int argc, char const *argv[])
{
        mystruct a;
        printf("\n %lu \n",sizeof(a));
        return 0;
}

符号なし整数は4バイトを占める32ビット整数です。メモリはメモリ内で連続して割り当てられます。


オプション1:

unsigned int a:1;       // First 4 bytes are allocated
unsigned int b:31;      // Will get accomodated in the First 4 bytes
unsigned int c:1;       // Second 4 bytes are allocated

出力:8


オプション2:

unsigned int a:1;       // First 4 bytes are allocated
unsigned int b:32;      // Will NOT get accomodated in the First 4 bytes, Second 4 bytes are allocated
unsigned int c:1;       // Will NOT get accomodated in the Second 4 bytes, Third 4 bytes are allocated

出力:12


オプション3:

unsigned int a:1;       // First 4 bytes are allocated
unsigned int b:1;       // Will get accomodated in the First 4 bytes
unsigned int c:1;       // Will get accomodated in the First 4 bytes

出力:4


オプション4:

unsigned int b:32;      // First 4 bytes are allocated
unsigned int a:1;       // Second 4 bytes are allocated
unsigned int c:1;       // Will get accomodated in the Second 4 bytes

出力:8

44
MdT

整列

コンパイラは、構造体のサイズを32ビットに丸めています。32ビットを参照しようとする各オブジェクトのサイズであり、同時にビットフィールドの順序を保持しています。

したがって、中央に32ビットのアイテムがあり、両側に1ビットのアイテムがある場合、これは3つの32ビットワードを割り当てるため、12バイトになります。

他の2つのケースでは、フィールドの順序を維持しながら、ビットフィールドシーケンスをパックできる32ビットオブジェクトの数が問題になります。

10
DigitalRoss

Steve jessop's answer によると、役立つかもしれないいくつかのドキュメントを追加することで彼の答えを満たします。

構造体または共用体のメンバーは、可変的に変更された型以外の完全なオブジェクト型を持つことができます。さらに、メンバーは、指定されたビット数(存在する場合は符号ビットを含む)で構成されると宣言できます。このようなメンバーはbit-fieldと呼ばれ、その幅の前にコロンが付きます

実装では、ビットフィールドを保持するのに十分な大きさのアドレス可能なストレージユニットを割り当てることができます。 十分なスペースが残っている場合、構造体の別のビットフィールドの直後に続くビットフィールドは、同じユニットの隣接するビットにパックされます。十分なスペースが残っていない場合、適合しないビットフィールドが次のユニットに配置されるか、隣接するユニットとオーバーラップするかは、実装によって定義されます。ユニット内のビットフィールドの割り当て順序(高位から低位、または低位から高位)は実装定義です。アドレス指定可能なストレージユニットの配置は指定されていません。

構造オブジェクト内では、非ビットフィールドメンバーとビットフィールドが存在するユニットには、宣言された順に増加するアドレスがあります。構造オブジェクトへのポインターは、適切に変換されて、その初期メンバーを指します(または、そのメンバーがビットフィールドである場合は、それが存在するユニットを指します)。その逆も同様です。名前のないパディングが構造体オブジェクト内にある可能性がありますが、最初はありません。

-ISO/IEC 9899:201x 6.7.2.1

9
yuan