Visual Basic の論理演算子とビット処理演算子
論理演算子は、Boolean 式を比較し、結果として Boolean 値を返します。And、Or、AndAlso、OrElse、および Xor 演算子は、オペランドを 2 つ取るので二項演算子と呼ばれます。一方、Not 演算子は、オペランドを 1 つ取るので単項演算子と呼ばれます。これらの演算子の中には、整数値に対してビットごとの論理演算を実行できるものもあります。
単項論理演算子
Not 演算子 (Visual Basic) は、Boolean 式の論理否定を求めます。これにより、オペランドの論理上の逆の値が得られます。式の評価が True の場合、Not は False を返します。式の評価が False の場合、Not は True を返します。次に例を示します。
Dim x, y As Boolean
x = Not 23 > 14
y = Not 23 > 67
' The preceding statements set x to False and y to True.
二項論理演算子
And 演算子 (Visual Basic) は、2 つの Boolean 式の論理積を求めます。両方の式の評価が True の場合、And は True を返します。少なくとも一方の式の評価が False の場合、And は False を返します。
Or 演算子 (Visual Basic) は、2 つの Boolean 式の論理和または包含を実行します。いずれかの式の評価が True の場合、または両方の式の評価が True の場合は、Or は True を返します。どちらの式の評価も True でない場合は、Or は False を返します。
Xor 演算子 (Visual Basic) は、2 つの Boolean 式の排他的論理和を求めます。どちらか一方の式の評価が True で、もう一方はそうでない場合は、Xor は True を返します。両方の式の評価が True の場合、または両方の式の評価が False の場合は、Xor は False を返します。
And、Or、および Xor 演算子の例を次に示します。
Dim a, b, c, d, e, f, g As Boolean
a = 23 > 14 And 11 > 8
b = 14 > 23 And 11 > 8
' The preceding statements set a to True and b to False.
c = 23 > 14 Or 8 > 11
d = 23 > 67 Or 8 > 11
' The preceding statements set c to True and d to False.
e = 23 > 67 Xor 11 > 8
f = 23 > 14 Xor 11 > 8
g = 14 > 23 Xor 8 > 11
' The preceding statements set e to True, f to False, and g to False.
論理演算子のショートサーキット
AndAlso 演算子 (Visual Basic)は、2 つの Boolean 式の論理積を求めるという点では And 演算子によく似ています。両者の大きな違いは、AndAlso はショートサーキットの動作を示すという点にあります。AndAlso 式の 1 番目の式の評価が False の場合は、2 番目の式の評価がどうなっても最終的な結果は変わらないので、2 番目の式は評価されないまま、AndAlso は False を返します。
同様に、OrElse 演算子 (Visual Basic)は、ショートサーキット評価で 2 つの Boolean 式の論理和を求めます。OrElse 式の 1 番目の式の評価が True の場合は、2 番目の式の評価がどうなっても最終的な結果は変わらないので、2 番目の式は評価されないまま、OrElse は True を返します。
ショートサーキットの長所と短所
ショートサーキットを使用すると、論理演算の最終的な結果に影響しない式は評価されないので、パフォーマンスが向上します。しかし、その式で追加の処理を実行していた場合は、ショートサーキットによりその処理がスキップされます。たとえば、その式に Function プロシージャの呼び出しが含まれている場合は、その式がショートサーキットされるとプロシージャが呼び出されないので、Function プロシージャ内の追加コードが実行されません。したがって、関数が実行されることがほとんどなく、正しくテストされないことがあります。また、プログラム ロジックが Function 内のコードに依存している場合もあります。
次の例は、And と Or、さらにそのショートサーキット版の演算子の違いを示しています。
Dim amount As Integer = 12
Dim highestAllowed As Integer = 45
Dim grandTotal As Integer
If amount > highestAllowed And checkIfValid(amount) Then
' The preceding statement calls checkIfValid().
End If
If amount > highestAllowed AndAlso checkIfValid(amount) Then
' The preceding statement does not call checkIfValid().
End If
If amount < highestAllowed Or checkIfValid(amount) Then
' The preceding statement calls checkIfValid().
End If
If amount < highestAllowed OrElse checkIfValid(amount) Then
' The preceding statement does not call checkIfValid().
End If
Function checkIfValid(ByVal checkValue As Integer) As Boolean
If checkValue > 15 Then
MsgBox(CStr(checkValue) & " is not a valid value.")
' The MsgBox warning is not displayed if the call to
' checkIfValid() is part of a short-circuited expression.
Return False
Else
grandTotal += checkValue
' The grandTotal value is not updated if the call to
' checkIfValid() is part of a short-circuited expression.
Return True
End If
End Function
上記の例では、checkIfValid() の呼び出しがショートサーキットされると、このプロシージャ内の重要なコードが実行されないという点に注意してください。1 つ目の If ステートメントは、12 > 45 が False を返すときでも checkIfValid() を呼び出します。なぜなら、And はショートサーキットを行わないからです。2 つ目の If ステートメントは、checkIfValid() を呼び出しません。12 > 45 が False を返すので、AndAlso が 2 つ目の式をショートサーキットするからです。3 つ目の If ステートメントは、12 < 45 が True を返すときでも checkIfValid() を呼び出します。なぜなら、Or はショートサーキットを行わないからです。4 つ目の If ステートメントは、checkIfValid() を呼び出しません。12 < 45 が True を返すので、OrElse が 2 つ目の式をショートサーキットするからです。
ビット処理演算
ビット処理演算子は、2 つの整数値をバイナリ (基数 2) の形式で評価します。対応する位置のビットを比較し、比較結果に基づいて値を割り当てます。次に And 演算子の例を示します。
Dim x As Integer
x = 3 And 5
この例では、x の値が 1 に設定されます。このような結果になる理由は次のとおりです。
2 つの値がバイナリとして扱われます。
バイナリ形式の 3 = 011
バイナリ形式の 5 = 101
And 演算子は、このバイナリ表現を 1 桁 (1 ビット) ずつ比較します。ある位置のビットが両方とも 1 だった場合は、結果の同じ位置に 1 が配置されます。いずれかが 0 だった場合は、その位置に 0 が配置されます。したがって、上の例は次のように評価されます。
011 (バイナリ形式の 3)
101 (バイナリ形式の 5)
001 (バイナリ形式の結果)
この結果は 10 進数として扱われます。001 という値は 1 のバイナリ表現なので、x = 1 となります。
ビットごとの Or 演算も同様です。ただし、その場合は、比較するビットの一方または両方が 1 のときに結果ビットが 1 になります。Xor では、比較するビットのいずれか一方だけが 1 のときのみ、結果ビットが 1 になります。Not のオペランドは 1 つだけであり、そのすべてのビット (符号ビットを含む) を反転させた値が結果になります。つまり、符号付き正数を与えると Not は必ず負数を返し、負数を与えると Not は必ず正数または 0 の値を返します。
AndAlso 演算子と OrElse 演算子はビット処理演算をサポートしません。
[!メモ]
ビット処理演算を実行できるのは整数型だけです。浮動小数点値に対してビット処理演算を実行するには、事前に整数型に変換する必要があります。