c++構造体のフィラーの効果は何ですか? 一部の c++ API でよく見かけます。例えば:
struct example
{
unsigned short a;
unsigned short b;
char c[3];
char filler1;
unsigned short e;
char filler2;
unsigned int g;
};
この構造体は、ネットワーク経由で転送するためのものです
struct example
{
unsigned short a; //2 bytes
unsigned short b;//2 bytes
//4 bytes consumed
char c[3];//3 bytes
char filler1;//1 bytes
//4 bytes consumed
unsigned short e;//2 bytes
char filler2;//1 bytes
//3 bytes consumed ,should be filler[2]
unsigned int g;//4 bytes
};
使用しているデータの形式を実際に制御していない場合があるためです。
形式は、制御できないものによって指定される場合があります。たとえば、システムとは異なるアライメント要件を持つシステムで作成される場合があります。
または、データには、コードが気にしないフィラー領域に実際のデータが含まれている場合があります。
これらのフィラーは通常、構造体の一部のメンバーが自然に整列するように明示的に挿入されます。つまり、構造体内のオフセットがそのサイズの倍数になります。
以下の例では、char を 1 バイト、short を 2 バイト、int を 4 バイトと想定しています。
struct example
{
unsigned short a;
unsigned short b;
char c[3];
char filler1;
unsigned short e; // starts at offset 8
char filler2[2];
unsigned int g; // starts at offset 12
};
フィラーを指定しない場合、コンパイラは通常、構造体メンバーの適切な配置を確保するために必要なパディング バイトを追加します。
ところで、これらのフィールドは、将来登場する可能性のある予約フィールドにも使用できます。
更新しました:
構造はネットワーク パケットであると述べたので、フィラーは別のホストから渡される構造と互換性のある構造を取得する必要があります。
ただし、この場合にフィラー バイトを挿入するだけでは不十分な場合があります (特に、移植性が必要な場合)。これらの構造体をそのままネットワーク経由で送信する場合 (つまり、送信用に別のバッファーに手動でパックする必要がない場合)、構造体をパックする必要があることをコンパイラーに通知する必要があります。
Microsoftコンパイラでは、これは次を使用して実現できます#pragma pack
。
#pragma pack(1)
struct T {
char t;
int i;
short j;
double k;
};
gccで使用できます__attribute__((packed))
struct foo {
char c;
int x;
} __attribute__((packed));
ただし、一部のシステムでは位置合わせされていないデータへのアクセスが[適切に]サポートされていない可能性があるため、多くの人は構造体を生のバイト配列に手動でパック/アンパックすることを好みます。
作業しているコードによっては、ワード境界 (あなたの場合は 32 ビット) で構造を整列させようとしている可能性がありますが、これは速度の最適化ですが、このようなことを行うことは適切な最適化コンパイラによって廃止されましたがコンパイラがこのコードを最適化しないように指示されている場合、またはコンパイラが非常にローエンド (組み込みシステムなど) である場合は、これを自分で処理する方がよい場合があります。基本的には、コンパイラをどれだけ信頼しているかにかかっています。
もう 1 つの理由は、ファイル形式の仕様に予約バイトが残されているバイナリ ファイルを書き込むためです。