macです。 Amaike takehiro <tanpa@xxxxxxxxx> wrote: > > イエローソフトは、確かビットフィールドを否定していなかったですか? > > どちらにしろ、ここの昔のログでも有る様に、ビットフィールドは、処理 > > 系依存です。必ず使える保証は無いんです。 > > 調べてみました。 > http://www.yellowsoft.com/user/user_a2.html > > YellowsoftさんのYCH8コンパイラはLSB、ルネサスはMSBなのですね。 > 他にも色々と制約があります・・・ YCH8も、MSB/LSBの割り当てを変更する機能もあるのですが、 取扱説明書で、「使わないほうが良い」と薦めています。 以下、その趣旨に私見を含めて、なぜ「使わないほうが良い」 か、まとめます。 1. bit fieldは、最終的にread modify writeになることがある。 read/writeが可能なメモリーには問題ないが、PxDDRのような、 write only registerでは、意図したことと異なる動作をする。 2. readに特別の意味がある場合に想定外の動作をする。 status registerなどは、ダミーリードしてから、 書き込むことで、フラグをクリアする物が多いが、 bit fieldを使用した場合read してしまったことに、 気付かない。 3. bit field, 構造体、共用体の割り当ては、処理系により異なる。 コンパイラーは、CPUのalignの制約上、word境界に当たるよう、 変数をpaddingしたり、順序を変えて、 詰め替える最適化をしたり、bit fieldの割り当てが異なったりする。 これらは、ANSIの規格ではないので、どう割り当てるかは、 コンパイラー次第となる。 つまり、これらを使って書いたプログラムは、移植性を失う。 4. bit操作命令の有無は、CPUによる。 H8/300Hには、bit操作命令があるが、 SHには、該当する命令がない。 その他のCPUでも、bit操作命令の有無はまちまちで、 効率化を狙って、bit fieldを使っても、最適化される可能性は、 CPUにbit操作命令があり、 コンパイラーがbit fieldをbit操作命令に 展開する使用になっているかどうかで、異なる。 場合によっては、非常に効率が悪化する。 B_IO.BYTE.b1 = 0; B_IO.BYTE.b2 = 1; B_IO.BYTE.b3 = 0; と3命令になることを期待しても、 実際には、6命令以上になることがある。 IO = (IO & 0xf8) | 0x02; と書いたほうが効率的で、 コンパイラーによる差異も、 小さくなる。 それに、read modify writeしていることを、 プログラマは、明確に自覚する。 5. 戻り値を「構造体」にした場合、 余分なメモリーを消費する。 スカラーは、多くの場合、レジスタで戻り値を受け渡すが、 構造体(のポインターではなくそのもの)を戻り値とする、 関数は、戻り値をメモリー上にコピーするので、 メモリーと処理時間が余分にかかる。 構造体を多用しているプログラマは、 それをあまり意識しなくなる傾向がある。 構造体を戻り値に使えない処理系もあり、 移植性の低下を招く。 6. 変数名が長くなり、ごちゃごちゃして読みにくい。 構造体、共用体を多用したプログラムは、 多くのフィールドを引き連れているため、 どうしても、 変数名が長くなる。 プログラムの可読性が低下すると、 バグを生じる温床になることが多い。 7. renesasのHeader Download Lisenceに拘束される。 http://www.renesas.com/jpn/products/mpumcu/tool/crosstool/iodef/index.html フリーソフトにしてソースを公開したくても、 Header Fileを含むことが出来ない。 8. Debugしにくい。 アセンブラレベルで、Debugが必要になったとき、 構造体の各フィールドがどこにアサインされているのか、 容易にわからず、面倒。 9. 過去のリソースを活用できない。 renesas(日立)が、Header Fileを公開する前に、 作成したプログラムは、大抵、構造体を使っていない。 これらを再利用したとき、 二つの形式のHeaderが混在することになり、 わかりにくいし、書き直すにしても、 せっかく「枯れきった」安全なリソースに、 エンバグするリスクを負う。 -- mac