TOP > eMbedded Visual C++ Tips > 第1回 ALIGNって何?(その1 〜構造体のパック〜)

eMbedded Visual C++ Tips 第1回 ALIGNって何?(その1 〜構造体のパック〜)

■ ALIGNについて

 ふと思いついたこの企画、この連載になるかどうか本人にも分からないが、eMbedded Visual C++でプログラミングする場合のTipsをx86のVisual C++と比較しながら不定期で書いていこうと思っている。

 で、記念すべき第1回はALIGNについてだ。僕自身はプログラムと言うと元々制御系が好きで規格モノ(AVとかの企画モノじゃないぞ)を良く書いている。LHAとかZIPとかを扱うソフトなんかはそういったところから出てきたものだ。これらのソフトは構造体なんかをかなり使っているのだが、これを書くにはちょっとしたコツがいる。

■ 構造体のサイズ

 例えばこんな構造体があるとする。

    struct simple {
        char c;
        int num;
    };
 このsimple構造体のサイズはsizeofで見るとx86でもXScaleでも8バイトになる。XScale等RISC CPUでは基本的にint等のマルチバイトのデータ型は、少なくとも奇数アドレスからのアクセスは許されない。x86では奇数アドレスからのアクセスは許されているものの、どちらもデータアクセスの効率化のため、4の倍数アドレスからアクセスされるようにコンパイラによってcharの後ろがパディングされたためだ。

 もちろんsimple構造体を単にデータの格納場所として使う分には全く問題はない。配列にした場合に少しデータ量が増えるぐらいである。しかし、simple構造体にファイルからデータを読み込む場合にはこのパディングは曲者だ。例えば以下のようなコードである。

    struct simple header;
    ReadFile(hFile,&header,sizeof(header),&nRead,NULL);
 わざわざ書かなくともお分かりかと思うが、このままでは実際にアクセスしたいデータの合計である5バイト(char + int)よりも多い8バイトがsimple構造体に読み込まれる。しかもパディング領域に読み込まれたデータにはアクセスできない。

■ 構造体のパッキング

 これを解消するには#pragma packで構造体を1バイト境界にパックすれば良い。

#pragma pack(1)     // 構造体パック始まり
    struct simple {
        char c;
        int num;
    }
#pragma pack()      // 構造体パック終わり
 #pragma pack(1)によりsimple構造体のメンバは1バイト境界上に配置されてサイズが5バイトになり、ファイルから意図したとおりにデータが読み込まれる。また、特定の構造体だけでなくすべての構造体をパックしたいならばコンパイラで/Zp1オプションを指定すれば良い。

 ただし、構造体の1バイトパッキングはRISC CPUでは本来できないはずの奇数アドレスからのマルチバイトデータの読み出しを、ソフトウェアにより見かけ上実現しているだけなので速度の低下に注意する必要がある。

(2003/11/20)


Copyright(C) 2003 モバイル開発系(K) All rights reserved.

[Home]