ビットの話


VBでAPIを使っていると、ビットの操作をしなければならない場合があります。
例えば、APIで引数にLongの値を渡す時に、何ビット目をONにするとか、
APIから返ってきた値の何ビット目がONで、何ビット目がOFFかチェックしたい等、この他にも多々あると思います。

私はこうした処理を、サブルーチン化してBasファイルにまとめておきます。
そして、使う時はそのBasをプロジェクトに追加して使う様にしています。
その方が効率が良いですし、記述する手間が省けます。
変更が必要なら、そのファイルからサブルーチンだけコピーして手直しするようにしています。

今回の話は、知っている人には「な〜んだそんな事」っとなってしまう話ですが、知らない人や初心者はのぞいてみて下さい。

ビットの操作

  1. ビットのシフト
    ビットのシフトとは、ビットの位置を全体的に右や左に移動させる事です。

    図で説明しますと、

    □□□□□□□□
    〇〇〇〇@〇〇〇←3ビット目がON、つまり8(先頭は0ビットとする

    左に1つシフトさせると、

    □□□□□□□□
    〇〇〇@〇〇〇〇←4ビット目がONになる、つまり16

    これをVBで行なう方法としては、掛け算・割り算を使います。

    例として、十進数でやってみますね。

    1を左にシフトするには10を掛けてやります。
    すると10になりますよね。
    同じように、左に3つシフトするには、1に1000を掛けてやります。

    反対に右にシフトするには、10で割ってやれば良いのです。

    これを二進数で行なうには2を掛けてやれば左にシフト・2で割れば右にシフトするという訳です。

    式にしてみると、

    シフトされた値シフトしたい値シフト数←左にシフト
    シフトされた値シフトしたい値シフト数←右にシフト

    こんな感じです。

    余談になってしまいますが、掛け算だけで右にシフトする事が出来ます。
    上の式のシフト数にマイナスの数字を入れると右にシフトします。
    右に1つシフトしたければ-1、3つシフトしけてれば-3ってな感じです。
  2. ビットのチェック
    指定した値の何ビット目がONになっているか調べたい時は、And演算子を使います。

    ONだと0以外が返るチェックしたい値 And 何ビット目をチェックするか

    こんな感じです。

    これもまた余談なんですが、先頭を調べるには0ビット目と言う事で調べます。
    2^0=1という事です。
  3. ビットのセット・リセット
    指定のビットをセットするには、Or演算子を使います。

    セットされた値セットしたい値 Or 何ビット目をセットするか

    こんな感じです。

    反対にリセットするには、Xor演算子を使います。

    リセットされた値リセットしたい値 Xor 何ビット目をリセットするか

    ちなみに、一度に複数のビットをセット・リセットする場合は、演算子をつなげて書いていきます。

    X=&HFF Or 2 Or 4 ←セットの場合
    X=&HF Xor 2 Xor 4 ←リセットの場合

    こんな感じです

バイト・ワード・ダブルワードの話

せっかくなので、バイトの話などもしようかなと思います。
(アルバイトじゃないですよ、うわっさむぅ)

APIの中には、戻り値Longの下位2バイトを使用したり、引数に上位2バイトと下位2バイトをくっつけて要求する物などがあります。
こう行った場合、結合や切り分けの処理を自前で行なわなければならず、大変難儀します。
それなので、こう言う処理もサブルーチン化しておくと便利です。
  1. Integer型をByte型に切り分ける
    下位バイトを取り出すのは簡単です。

    下位バイト=取り出したい値 And &HFF

    これは、上のビットセットの応用です。
    上位バイトの方は、ちょっとテクニックがいります。
    なぜかというと、VBのInteger型は符号付の為、ビットシフト等で取り出そうとするとおかしくなります。

    私はこうしています。

    上位バイト = IIf(取り出したい値 < 0, (取り出したい値 + &H10000) \ &H100, 取り出したい値 \ &H100)

    取り出したい値が負の値の場合、一度Longにして、シフトして取り出しています。
  2. Byte型を結合してInteger型にする
    こちらも、上位バイトがネックになります。

    結合された値 = IIf(上位バイト > &H7F, (下位バイト + (CLng(上位バイト) * &H100)) - &H10000, 下位バイト + (上位バイト * &H100))

    上の、切り分けの応用です。
  3. Long型をInteger型に切り分ける
    今度は、Long型を2バイトづつに切り分ける方法です。

    下位2バイトはこんな感じです

    下位2バイト = IIf((切り分けたい値 And &HFFFF&) > &H7FFF, (切り分けたい値 And &HFFFF&) - &H10000, 切り分けたい値 And &HFFFF&)

    上位2バイトはこんな感じです

    上位2バイト = (切り分けたい値 And &HFFFF0000) \ &H10000
  4. Integer型を結合してLong型にする
    今度は、Integer型を結合してLong型にする場合です。

    こんな感じです

    結合した値 = (下位2バイト And &HFFFF&) Or (上位2バイト * &H10000)

今回の話は、秀和システムから出版されているWindows98APIリファレンスに載っている物を、私なりにアレンジしてみました。

さらに、この章で使ったサブルーチンをBasファイルにしてありますので、使用して下さい。
このファイルの中には、上記の他に、APIを使ってメモリコピーして切り分けたり結合したりする方法が載っています。
そして、Currency型を使ったLong型を結合して8バイトにする方法等も載っています。
参考にしてみてください。

bit.lzh 1,863 Byteこの章のサンプルが見たい方はこちら