タグ

ブックマーク / proger.blog10.fc2.com (2)

  • ビットシフトの落とし穴 - 算術シフトと論理シフト - 職業としてのプログラミング

    C言語には、ビットシフト演算子というものがあります。左シフト演算子(<<)と右シフト演算子(>>)です。同じビット演算でも、ビット単位の論理和(|)や論理積(&)、NOT(~)等はの方は、フラグ型の変数の処理で使われる事が多い気がしますが、ビットシフトの方は使用されるケースはあまりないかもしれません。 さて、このビットシフト演算子で時々問題になるのが、符号ビットが立っている時の右シフト演算です。見逃されがちなポイントは、 型によって挙動(算術シフトか論理シフトか)がかわることがある C言語の規格として、算術シフトか論理シフトかは不定 Nbitの算術シフトと2のN乗での除算は等価ではない といったところにあります。 算術シフト(shift arithmetic)と論理シフト(shift logical:又は0充填シフト)という言葉をご存知ない方のためにちょっと説明を書いておくと、シフトによっ

    rawwell
    rawwell 2009/04/05
    『signedの場合は算術右シフト(sarl)命令、unsignedの場合は、論理右シフト命令(shrl)になっているのが確認できます。』
  • charの落とし穴 - 暗黙の型変換と符号拡張 - 職業としてのプログラミング

    前回unsignedでよく陥りがちなバグについて触れました。今回はその続編で、char型での落とし穴として、いわゆる符号拡張(sign extension)と暗黙の型変換(inplicit conversion)について説明します。 次のコードの問題点はわかるでしょうか? typedef char value_t; #define INVALID 0xff /* valがINVALIDなら0、それ以外で1を返す */ int check(value_t val) { switch (val) { case INVALID: return 0; default: return 1; } 一見問題なさそうに思えますが、実際このコードをコンパイルして、valにINVALID(0xff)を指定しても1が帰ってきます。なぜでしょう? C言語のswitch分では、比較値はint型として扱われます。よっ

    rawwell
    rawwell 2009/04/05
    『変換時には符号拡張が行われ0xff(charの-1)は0xffffffff(intの-1:intが32bitの場合)となってしまいます。よって、0xffとは一致しないのです』
  • 1