消えるビット

今回も組み込みのちょっとしたお話。ま、ビットシフトを行う上での注意は組み込みに限ったことではないですが…。とりあえず以下のコードをご覧アレ。

#define FOO_VALUE (1 << 16)
なんの変哲もないマクロ。1が左に16ビットシフトされます。しかし、このコードには罠が!まあ、コンパイラ依存ではありますが、組み込みで使用するコンパイラはdefineやenumが32bitで確保されるとは限りません。コンパイラによっては値の格納できる最小のサイズが割り当てられます。この場合も1がbyteサイズのメモリに割り当てられ、それを16ビットシフト。結果、シフトした段階でビットは溢れている場合があります。こういったマクロを利用してレジスタやら、メモリマップドIOにアクセスすると、意図した制御ができないことがよくあります。こういったマクロを書く場合、例えばarmccでは以下の様にします。

#define FOO_VALUE (1ul << 16)
こうすることで意図しないビットあふれは発生しなくなります。原因不明の動作不良が案外こんなオチだったりします。要はコンパイラの仕様書はよく読めってことです。