ビットの話
VBでAPIを使っていると、ビットの操作をしなければならない場合があります。
例えば、APIで引数にLongの値を渡す時に、何ビット目をONにするとか、
APIから返ってきた値の何ビット目がONで、何ビット目がOFFかチェックしたい等、この他にも多々あると思います。
私はこうした処理を、サブルーチン化してBasファイルにまとめておきます。
そして、使う時はそのBasをプロジェクトに追加して使う様にしています。
その方が効率が良いですし、記述する手間が省けます。
変更が必要なら、そのファイルからサブルーチンだけコピーして手直しするようにしています。
今回の話は、知っている人には「な〜んだそんな事」っとなってしまう話ですが、知らない人や初心者はのぞいてみて下さい。
ビットの操作
- ビットのシフト
ビットのシフトとは、ビットの位置を全体的に右や左に移動させる事です。
図で説明しますと、
□□□□□□□□
〇〇〇〇@〇〇〇←3ビット目がON、つまり8(先頭は0ビットとする)
左に1つシフトさせると、
□□□□□□□□
〇〇〇@〇〇〇〇←4ビット目がONになる、つまり16
これをVBで行なう方法としては、掛け算・割り算を使います。
例として、十進数でやってみますね。
1を左にシフトするには10を掛けてやります。
すると10になりますよね。
同じように、左に3つシフトするには、1に1000を掛けてやります。
反対に右にシフトするには、10で割ってやれば良いのです。
これを二進数で行なうには2を掛けてやれば左にシフト・2で割れば右にシフトするという訳です。
式にしてみると、
シフトされた値=シフトしたい値*2^シフト数←左にシフト
シフトされた値=シフトしたい値¥2^シフト数←右にシフト
こんな感じです。
余談になってしまいますが、掛け算だけで右にシフトする事が出来ます。
上の式のシフト数にマイナスの数字を入れると右にシフトします。
右に1つシフトしたければ-1、3つシフトしけてれば-3ってな感じです。- ビットのチェック
指定した値の何ビット目がONになっているか調べたい時は、And演算子を使います。
ONだと0以外が返る=チェックしたい値 And 2^何ビット目をチェックするか
こんな感じです。
これもまた余談なんですが、先頭を調べるには0ビット目と言う事で調べます。
2^0=1という事です。- ビットのセット・リセット
指定のビットをセットするには、Or演算子を使います。
セットされた値=セットしたい値 Or 2^何ビット目をセットするか
こんな感じです。
反対にリセットするには、Xor演算子を使います。
リセットされた値=リセットしたい値 Xor 2^何ビット目をリセットするか
ちなみに、一度に複数のビットをセット・リセットする場合は、演算子をつなげて書いていきます。
X=&HFF Or 2 Or 4 ←セットの場合
X=&HF Xor 2 Xor 4 ←リセットの場合
こんな感じですバイト・ワード・ダブルワードの話
せっかくなので、バイトの話などもしようかなと思います。
(アルバイトじゃないですよ、うわっさむぅ)
APIの中には、戻り値Longの下位2バイトを使用したり、引数に上位2バイトと下位2バイトをくっつけて要求する物などがあります。
こう行った場合、結合や切り分けの処理を自前で行なわなければならず、大変難儀します。
それなので、こう言う処理もサブルーチン化しておくと便利です。
- Integer型をByte型に切り分ける
下位バイトを取り出すのは簡単です。
下位バイト=取り出したい値 And &HFF
これは、上のビットセットの応用です。
上位バイトの方は、ちょっとテクニックがいります。
なぜかというと、VBのInteger型は符号付の為、ビットシフト等で取り出そうとするとおかしくなります。
私はこうしています。
上位バイト = IIf(取り出したい値 < 0, (取り出したい値 + &H10000) \ &H100, 取り出したい値 \ &H100)
取り出したい値が負の値の場合、一度Longにして、シフトして取り出しています。- Byte型を結合してInteger型にする
こちらも、上位バイトがネックになります。
結合された値 = IIf(上位バイト > &H7F, (下位バイト + (CLng(上位バイト) * &H100)) - &H10000, 下位バイト + (上位バイト * &H100))
上の、切り分けの応用です。- Long型をInteger型に切り分ける
今度は、Long型を2バイトづつに切り分ける方法です。
下位2バイトはこんな感じです
下位2バイト = IIf((切り分けたい値 And &HFFFF&) > &H7FFF, (切り分けたい値 And &HFFFF&) - &H10000, 切り分けたい値 And &HFFFF&)
上位2バイトはこんな感じです
上位2バイト = (切り分けたい値 And &HFFFF0000) \ &H10000- Integer型を結合してLong型にする
今度は、Integer型を結合してLong型にする場合です。
こんな感じです
結合した値 = (下位2バイト And &HFFFF&) Or (上位2バイト * &H10000)
今回の話は、秀和システムから出版されているWindows98APIリファレンスに載っている物を、私なりにアレンジしてみました。
さらに、この章で使ったサブルーチンをBasファイルにしてありますので、使用して下さい。
このファイルの中には、上記の他に、APIを使ってメモリコピーして切り分けたり結合したりする方法が載っています。
そして、Currency型を使ったLong型を結合して8バイトにする方法等も載っています。
参考にしてみてください。
この章のサンプルが見たい方はこちら