C言語における構造体、連合体のメンバーメモリ配置状況


前言
最近のプロジェクトでは、小さな問題が発生しました。データプロトコルの転送過程で、解析を容易にするために構造体を定義しました。データのポインタが関数に入ってきた時、定義された構造体を使って強制的に転化しました。構造体を定義していますが、データの配置には気づきませんでした。底の実装では、私が入ってきたデータのブザーは整然と並んでいます。atribute_((u_u u u u u u)packed(u)もしくは_packedは強制的にデータを配置して、構造体のメンバーが実際に並べばメンバーの中で最大の変数のフォーマットによって行われます。足りないところは仮想補足されます。
構造体のデータ配置について説明します。
 画像記述の2つの構造的整列を実現する声明は、構造体と結合した声明に適用される。

次に、構造体を宣言するいくつかのグループのメンバー変数の配置方法を示します。

/*     */
struct stc
{
    char one;
    short two;
    char three;
    int four;
} c,d;


int main (void)
{
    c.one=1;
    return 0;
}

最初の例示的なコードは下のメモリ配列の画像に合わせて、正常には特殊な声明がない場合、構造体はメモリ配列において構造体メンバーの中で最大の変数の大きさに従って配列されていることがわかる。
第一の例示コードの中で、最大のメンバー変数はint型で、一つのint型は私が使っている32ビットARM環境の中で4 byteを占めています。だから、配列の中で、一番小さい配列単位は4 byteです。他のタイプはcharが1 byteを占めて、sharは2 byteを占めています。第一行の4 byteの中で、一つのchar+一つのショートタイプは3 byteです。2行目の4 byteの中には、まだ1つのcharとintが残っています。intは単独で1行を占めています。だから、charは3 byteを追加して並べばいいです。

/*     */
struct __attribute__((packed)) stc
{
    char one;
    short two;
    char three;
    int four;
} c,d;


int main (void)
{
    c.one=1;
    return 0;
}

第二のコード例は下のメモリ配列の画像に合わせて表示されます。atribute((u)この声明は、関連する構造体と連合体が強制的に1バイトずつ整列させるという意味です。したがって、メモリ内の配列には、1 byteのデータ配置によって、メンバー変数が密接に配置されています。

/*     */
#pragma pack (2)
struct stc
{
    char one;
    short two;
    char three;
    int four;
} c,d;


int main (void)
{
    c.one=1;
    return 0;
}


/*     */
#pragma pack (4)
struct stc
{
    char one;
    short two;
    char three;
    int four;
} c,d;


int main (void)
{
    c.one=1;
    return 0;
}

第3、4つの例示的なコードは下のメモリ配列のイメージに合わせて、コードには「〓pragma pack(n)」という声明が使われています。この声明の意味は、関連する構造体が連合体に強制的にNバイト整列させ、この声明と__u u u_uatribute((u)機能は似ていますが、_atribute((u)packed)は1バイトだけ強制的に整列することができますが、バイト数を揃えることはnによって制御されるので、多くの柔軟性があります。具体的な使用は、下の図のメンバーの配置状況から分かります。ここでは説明を省略します。

締め括りをつける
ここでC言語の構造体、連合体のメンバーメモリの配置についての記事を紹介します。C言語構造体、連合体の内容については以前の文章を検索してください。