Why is &&
preferable to &
and ||
preferable to |
?
I asked someone who\'s been programming for years a
When used in a logical expression such as an if statement &&
preferable because it will stop evaluating expressions as soon as the first false result is encountered. This is possible because a false value will cause the entire expression to be false. Similarly (and again in logical expressions) ||
is preferable because it will stop evaluating expressions as soon as it encounters a true expression because any true value will cause the entire expression to be true.
If however the expressions being or-ed or and-ed together have side effects, and you want all of these to happen as a result of your expression (regardless of the outcome of the logical expression), then &
and |
could be used. Conversely, the &&
and ||
operators can be useful as guards against unwanted side-effects (such as a null pointer causing an exception to be thrown).
The &
and |
operators can also be used with integers and in this case they produce an integer result which is the two operands and-ed or or-ed together at the bit level. This can be useful when an integer value's binary bits are used as an array of true and false values. To test whether a certain bit is on or off, a bit-mask is bitwise and-ed with the value. To turn a bit on, the same mask can be bitwise or-ed with the value. Finally to turn a bit off, the bitwise complement (using ~
) of a mask is bitwise and-ed with the value.
int a = 0; // 0 means all bits off
a = a | 4; // set a to binary 100
if ((a & 4) != 0) {
// will do something
}
a = a & (~4) // turn bit off again, a is now 000
In languages other than C#, care must be taken with the logical versus bitwise modes of & and |. In the code above, the if
statement's conditional expression (a & 4) != 0
is a safe way to express this condition, but in many C like languages, conditional statements can simply treat zero integer values as false and non-zero integer values as true. (The reason for this relates to the conditional branch processor instructions available, and their relationship to the zero flag that is updated after every integer operation.) So the ìf
statement's test for zero can be removed and the condition could be shortened to (a & 4)
.
This could cause confusion and maybe even problems when expressions combined using the bitwise and operator return values that don't have bits that line up. Consider the following example where the side-effects of two functions are desired, before checking that they were both successful (as defined by them returning a non-zero value):
if (foo() & bar()) {
// do something
}
In C, if foo()
returns 1 and bar()
returns 2, the "something" won't be done because 1 & 2
is zero.
C# requires conditional statements like if
to have a boolean oeprand, and the language doesn't allow an integer value to be cast to a boolean value. So the code above would generate compiler errors. It would more correctly be expressed as follows:
if (foo() != 0 & bar() != 0) {
// do something
}