2016-07-19 22 views
1

私はCプログラムで以下の構造体を持っています。C内の構造体を含む構造体のバイト割り当て

typedef struct 
{ 
    unsigned char msg_id : 8; 
    unsigned char msg_num : 8; 
} Message_Header_Type; 
typedef struct 
{ 
    Message_Header_Type header; 
    int msg[32]; 
} Raw_Message_Type; 

Raw_Message_Typeにおけるヘッダは4つのバイトを取っているが、私はそれだけが唯一の2は、どのように私はこれをやって行くだろう撮りたいという私は何を見ているのですか?

+1

構造体をパックすると、 'Message_Header_Type'を2バイトまで下げることができますが、' Raw_Message_Type'では 'header'に2バイトのパディングが続いている可能性があります。 4バイトの境界に揃えられます。 – Dmitri

答えて

2

Message_Header_typeはまだ2つのバイトを取っているが、あなたのRaw_Message_Typeは、132バイト長の代わりに、あなたが予想される130バイトであるので、コンパイラは、アライメントの理由で構造をパディングされます。これはおそらく、32ビットの整列されたアクセスがプロセッサ上でより効率的であるためです。

gccを使用している場合は、#pragma packを使用して使用している4バイトの境界ではなく、2バイト境界で整列するようにコンパイラに指示できます。ファイル内の固定サイズの構造体を使用しますが、プロセッサが好むものとは異なる梱包を使用するための(光)パフォーマンスの低下があるかもしれないことに注意してたときに、このような

typedef struct 
{ 
    unsigned char msg_id : 8; 
    unsigned char msg_num : 8; 
} Message_Header_Type; 
#pragma pack(push, 2) // save current alignment and set to 2-byte boundaries 
typedef struct 
{ 
    Message_Header_Type header; 
    int msg[32]; 
} Raw_Message_Type; 
#pragma pack(pop) // restore the previous alignment 

特別な梱包がしばしば必要です。この特定の場合、32 msg [] intはすべて、ご使用のプラットフォームの優先アライメントから2バイト離れた位置になります。

+0

これは機能しました。 Visual Studioを使用しているので、他の回答の「__attribute__」はコンパイルされませんでした。しかし、私は彼らが他人を助けると確信しています。 – bsh152s

3

struct packingはプラットフォームとコンパイラに依存していますが、その詳細はC標準では指定されていません。 GCCのドキュメントから

typedef struct __attribute__((__packed__)) 
{ 
    unsigned char msg_id; 
    unsigned char msg_num; 
} Message_Header_Type; 

はGCCでは、32ビットプラットフォーム上で、あなたはサイズ2の構造体を取得するには、次の何ができる

packed この属性は、 enum、struct、または共用体の型定義に添付され、型の表現に最低限必要なメモリーが使用されることが指定されています。

+0

私はあなたのアプローチが私のものよりも好きなので、私はupvotingしています。 –

+0

@JoshSanfordプラグマについて知っておきたい。 +1 – sergej

1

Cの実装では、メンバー間、末尾、またはその両方にレイアウトを埋め込むことができます。整列のためにそうするのが一般的です。コンパイラーがパディングに影響を与える、またはオーバーライドするメカニズムを提供するのも一般的ですが、詳細は実装固有のものです。 GCCで

は、例えば、あなたのstructs両方にpacked属性を適用できます。

typedef struct __attribute__((__packed__)) 
{ 
    unsigned char msg_id : 8; 
    unsigned char msg_num : 8; 
} Message_Header_Type; 

typedef struct __attribute__((__packed__)) 
{ 
    Message_Header_Type header; 
    int msg[32]; 
} Raw_Message_Type; 

他のいくつかの実装では、GCCのアプローチを借ります。いくつか同じ目的のためにpragmaを使用します。いくつかは他のメカニズムを提供します。コンパイラのドキュメントをチェックする必要があります。

0

構造体オブジェクトは、メンバビットフィールドで使用されるビットの合計のサイズを保証しません。これは、パディングが原因です。

あなたの場合、Raw_Message_Typeには別のメンバーint msg[32];がありますが、 msg [0]が4バイトの境界に揃えられるように、2バイト以上を目的に合わせて使用​​することは理にかなっています。

Message_Header_Type obj; 
printf("Size : %zu\n",sizeof(obj)); 

が結果としてあなたに2を与えるだろうという良いチャンスがあります。あなたが期待するようRaw_Message_Typeの内部

関連する問題