イミディエイトウィンドウに "? 255 * 200" と入力して [Enter] を力いっぱい叩くと、オーバーフローのエラーが表示される。
文字列の上位バイトと下位バイトから2バイト文字、要するに全角文字の文字コード(Unicode値)を算出する以下のコードを書いてみたところ、文字列 "0123456789" あたりで撃沈した。
'-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- ' 機 能:上位バイトと下位バイトからInteger値を算出する ' 引 数:(i)HighByte … 上位バイト ' (i)LowByte … 下位バイト ' 返り値:Integer値 '=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= Private Function MakeInteger(ByVal HighByte As Byte, ByVal LowByte As Byte) As Integer MakeInteger = CInt((HighByte * &H100) + LowByte) End Function とりあえず、
Call MakeInteger(127, 255) '値にすると32767 → 通常運転 Call MakeInteger(128, 255) '値にすると33023 → オーバーフロー発生 と、実行してくれたまえ。VB の Integer型は2バイトでその範囲は -32768 〜 32767。C言語と違って unsigned を指定することは出来ないので、32767 を超えるとたちまちオーバーフローである。従って上位バイトが 127 を超えていたら、負(マイナス)の方向へ値をひっくり返す処理を記述しなければならない。上記の場合だとInteger型で保持させるには -32513 という値を算出する必要がある。それでは実際にコードを書いてみましょう。 '-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- ' 機 能:上位バイトと下位バイトからInteger値を算出する ' 引 数:(i)HighByte … 上位バイト ' (i)LowByte … 下位バイト ' 返り値:Integer値 '=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= Private Function MakeInteger(ByVal HighByte As Byte, ByVal LowByte As Byte) As Integer If HighByte > 127 Then MakeInteger = (((HighByte - 128) * &H100) Or &H8000) + LowByte Else MakeInteger = (HighByte * &H100) + LowByte End If End Function これで問題なしである。上記でも書いた通り、32767 を超えた場合は &H8000(=-32768) を加算して負(マイナス)の世界へ値を反転させ、Integer型としての整合性を強引に保たせている。…でも見た感じ何をしているかさっぱり分からない気がする。 上記の処理を感覚的に分かるように書いてみたい、ということで2秒ほど考えたところAPI関数の CopyMemory を使用するのが簡単であろうという結論に達した。この関数の機能や使い方を理解しているのであれば、感覚的(主に視覚的)に理解できるコードを書くことが出来る。ちなみに CopyMemory というのは仮の別名であって、kernel32.dll には "RtlMoveMemory" という名前で登録されている。注意されたし。
'API宣言
'-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- ' 機 能:上位バイトと下位バイトからInteger値を算出する ' 引 数:(i)HighByte … 上位バイト ' (i)LowByte … 下位バイト ' 返り値:Integer値 '=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= Private Function MakeInteger(ByVal HighByte As Byte, ByVal LowByte As Byte) As Integer Call CopyMemory(ByVal VarPtr(MakeInteger) + 1, ByVal VarPtr(HighByte), 1) '上位 Call CopyMemory(ByVal VarPtr(MakeInteger), ByVal VarPtr(LowByte), 1) '下位 End Function
Integer型変数の上位に引数の上位バイトを、Integer型変数の下位に引数の下位バイトをメモリコピーしているだけの簡単な処理のはずである。
[参考1]
[参考2] '-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- ' 機 能:RGB値をARGB値に変換する ' 引 数:(i)RGBValue … RGB値 ' (i)Alpha … Alpha値(省略時は0(=黒)が設定される) ' 返り値:ARGB値 '=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= Public Function RGB2ARGB(ByVal RGBValue As Long, Optional ByVal Alpha As Byte = vbBlack) As Long Dim R&, G&, B&, A As Long 'RGB値をR、G、Bに分解 R = RGBValue And &HFF& G = (RGBValue And &HFF00&) \ &H100& B = (RGBValue And &HFF0000) \ &H10000 '桁あふれ対策 If Alpha > 127 Then A = (Alpha - 128) * &H1000000 Or &H80000000 Else A = Alpha * &H1000000 End If RGB2ARGB = (B * &H1) Or (G * &H100&) Or (R * &H10000) Or A End Function |