memo/20090908
created 2009-09-08 modified 2009-10-01
ビットフィールド使うと移植性がなくなる件
リンク | 備考 |
---|---|
mozilla C++ Portability Guide |
uint8_t aaa:4; uint8_t bbb:2; uint32_t ccc:26;を、
uint32_t aaa:4; uint32_t bbb:2; uint32_t ccc:26;とかやっても、ダメぽ)。なんでかというと...
リンク | 備考 |
---|---|
Sun Studio 12: C ユーザーズガイド 付録 E ISO/IEC C90 の処理系定義の動作 | |
構造体メンバの配置 |
C/C++ の仕様としては... 構造体の定義順でアドレスが増加しないといかん、ということらしい。でもその仕様はリトルエンディアンかビッグエンディアンかはリンクしないのでややこしいことになる。
リンク | 備考 |
---|---|
Javaでビットフィールド | これはJavaのページだけど。 |
【結論】
構造体メンバの定義は最小単位でもバイトにして、バイトをまたがるメンバはマスクとシフトで乗り切る。
uint16_t や uint32_t の場合、シリアライズ、デシリアライズのときは、ちゃんとバイトオーダ変換する。
uint32_t aaa_bbb_ccc;
以上、調べた結論は「ビットフィールドは使わない」なんですが、どういう書き方をすれば、ほぼ統一できるのかなぁ、と考えて、やってみた案をメモ。
【没案】
・パケットフォーマットを決めるとき、32ビット区切りをまたぐフィールドは定義しない。
・バイト単位に収まらないフィールドがある32ビットを、ひとまとまりとして、uint32_t との union で定義する。で、メンバは32ビット内の低位から並べる。
・シリアライズ、デシリアライズのときは、uint32_t の値として、ちゃんとバイトオーダ変換する。
これ、結局ソースが煩雑になり、メリット皆無になります。
そもそもパケットのフォーマットどおりの構造体を定義するのはバッファポインタを構造体ポインタでキャストするといいじゃん、というアイデアが元だけど、もうその領域じゃなくなる。没。
追記:2009/10/01
gccには、ms-vc流のパッキングを行うコンパイラオプションやプラグマ指定があるらしいです。キーワードは
-m(no-)ms-bitfields __attribute__((__ms_struct__)) #pragma ms_struct [on|off|reset]
あたりの模様。