The previous blogpost discussed the difference between And vs &&, and Or vs || in conditional statements. It showed why && and || should be used instead of And and Or. The post also contained an example where it is legitimate to use the And operator:
Local Int x = %111 ' binary notation of 7 If x And %11 > 0 ' test if lower 2 bits are set ' do something EndIf
However, this condition is true for the wrong reasons. The condition is also true when only bit one is set. To prevent this and only check for the two lower bits we could change it into:
If x And %11 == 3 ' test if lower 2 bits are set
This seem to work ok, but the condition is still true for the wrong reason and that's gone haunt you. Let's try something different, let's test if bit 1 (value is 2) is set using the same method:
If x And %11 == 2 ' test if bit 1 is set Message "Condition is True" Else Message "Condition is False" EndIf
When we run this code, the program displays:
As you can see, the statement does not recognize that bit 1 is set (binary %10 == 2), despite the fact that the bit is 1.
So, what is going on here? Can't we trust And anymore? Maybe it is a bug? It is not a bug; it works like this is in any language and to understand this behavior we need to look at the operator precedence table. The helpfile contains the table under the topic name Operator Hierarchy:
( ) | parenthesis |
---|---|
+ - ~ ! | unary plus, unary minus, bitwise NOT, logical NOT |
$ & | explicit string addition |
^ | the power of |
* / | multiply, divide (floating-point) |
\ Div Mul | integer division, integer multiplication |
% Mod Fmod | integer and the floating point modulo |
+ - Add Sub | addition (the string addition, too) and subtraction |
<< >> Shl Shr Rol Ror | all shift and rotate operators (also: Shl%, Rol|, Sar8, etc.) |
%& | bitwise And |
%| | the bitwise Or |
= == < > <= >= != | all comparisons (also: NEAR ...) |
And | bitwise And |
Or | bitwise Or |
Xor Imp Eqv | bitwise exclusive Or, implication and equivalence |
&& | logical And |
|| | logical Or |
^^ | logical exclusive Or |
Not | bitwise complement |
When an expression is evaluated the rules of operator precedence are applied. For instance, multiplication and division go before addition and subtraction. The table shows this by placing the * and / operators before (or above) + and -. Now look at the And operator; it comes after the comparison operators. This means that if an expression contains a comparison operator, it is evaluated (computed/calculated) before the And operator is applied. In our case, the part %11 == 2 is evaluated before And is applied. Since %11 = 3, 3 is not equal to 2 (results in False) and x And 0 is always 0, the result is 0 (False). These are the steps involved in the evaluation:
(Step 1) If x And %11 == 2
(Step 2) If x And False
(Step 3) If x And 0
(Step 4) If 0
Can you now see why the original example form above results in True?
If x And %11 == 3 ' True for the wrong reason
The problem can be solved by using either parenthesis or %&:
If (x And %11) == 2 ' test if bit 1 is set
If x %& %11 == 2 ' GB way
In all other languages than GB the first solution is used. However GB defines an additional 'And' operator with a higher precedence that comes before the comparison operators: the %& operator. See the table for its location.
The Or operator suffers from the same problem, so GB defines an or-operator with higher precedence, the %| operator.
Is there a moral to this story? Try to avoid the use of And (&) and Or (|), unless - for instance - when translating C/C++ code to GB. (C/C++ does not support %& and %|.) Otherwise you might prefer the use of %& and %|.
No comments:
Post a Comment