5

一部のデータを構造体にパックしようとしています。

構造体の定義は次のとおりです。

#pragma pack(push)
#pragma pack(1)
struct Data
{
    unsigned char i:2;
    unsigned short r:14;
    unsigned short c:14;
};
#pragma pack(pop)

ビット数が 30 でパックが 1 であるため、この構造体のサイズは 4 である必要があると理解していますが、コンパイラーはサイズが 5 バイトであると言っています。

Visual Studio 2012 を使用しています。

これらはビットフィールドであることに注意してください。

このサイズは 4 です。

struct Data
{
    unsigned short i:2;
    unsigned short r:14;
    unsigned short c:14;
};
4

3 に答える 3

8

The exact layout of bitfields in memory is not specified by the standard. However, I'm fairly convinced that if you use unsigned int for all your fields, like this:

struct Data
{
    unsigned int i:2;
    unsigned int r:14;
    unsigned int c:14;
};

your data will be packed into one 30-bit integer value. However, since you have declared the first field a char, it can not hold a 14-bit value, and thus is seen as a separate field.

(gcc gives 4 bytes for both variants, which is one reason I say that there are differences between compilers - hence nothing in the standard stating that the fields are not defined in the standard)

于 2013-05-29T13:03:24.150 に答える
3

pack プラグマがメンバーの配置を制御するためです。1 と言うと、メンバーがバイト制限で整列されていることを意味します。つまり、メンバーはすべてのバイトから開始できます。しかし、サイズ 1、2、および 2 の 3 つのメンバーがあるため、結果のサイズは 5 になります。これを使用しない場合、コンパイラは通常、1 よりも高いアラインメントを使用します。これは、CPU が複数の要素にアクセスする方がはるかに効率的であるためです。特定の値の(あなたの場合、pack pragmeを削除すると6バイトを占めるため)。

Pack は、ビット レベルでの構造体のパッキングではありません。

EDIT : このステートメントを明確にするために、Visual Studio の pack プラグマ ドキュメントから引用します。

n (オプション): パッキングに使用する値をバイト単位で指定します。n のデフォルト値は 8 です。有効な値は 1、2、4、8、および 16 です。メンバーの配置は、n の倍数またはメンバーのサイズの倍数のいずれかである境界上にあります。より小さいです。

編集 2 (質問からの編集後): 最初のケースのビットフィールドがマージされない (および上記の動作を示す) 理由は、Visual Studio が構造のビットフィールド メンバーを 1 つのデータ要素にのみマージするためです。 . したがって、すべてが短いと宣言された場合、彼はそれらをマージしようとします (この場合は成功します) が、1 つが異なる場合はマージできません。

于 2013-05-29T13:04:36.930 に答える