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