41

When used with boolean operands, & and | become logical operators per Section 15.22.2 of the JLS. Unlike && and ||, however, these don't short-circuit; they always evaluate both sides. I have a silly question: Why are the less-efficient non-short-circuit logical operators (&, |) still there, when we have the more-efficient short-circuit logical operators (&&, ||)? I mean, what is the real usage of the non-short-circuit logical operators, as opposed to with the short-circuit logical operators? In other words, what is the usage of always evaluating both sides by using the non-short-circuit logical operators?

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
ironwood
  • 8,936
  • 15
  • 65
  • 114
  • 7
    It's not about *efficiency*, they have different *semantics* – Johan Sjöberg Feb 13 '12 at 17:23
  • 2
    It's what C does. / Actually in some circumstances they can be faster, because they may reduce branching. There can also be side-effects in evaluating the rhs (evil). – Tom Hawtin - tackline Feb 13 '12 at 17:24
  • 1
    @TomHawtin-tackline: C doesn't short-circuit `&` and `|`. Like Java, it short-circuits `&&` and `||`, but not `&` and `|`. – T.J. Crowder Feb 13 '12 at 17:27
  • this may be of help: [effect-of-a-bitwise-operator-on-a-boolean-in-java](http://stackoverflow.com/questions/1724205/effect-of-a-bitwise-operator-on-a-boolean-in-java) – wmz Feb 13 '12 at 17:51
  • Thanx for the edits T.J. Crowder – ironwood Feb 14 '12 at 01:11
  • Short-circuit operators are not always more efficient, see [Code efficiency](http://en.wikipedia.org/wiki/Short-circuit_evaluation) – Johnny May 28 '13 at 02:47
  • I think you mean **what is the use**, not **what is the usage**; I wasn't completely certain, though, so I didn't change it. Please confirm. – Mathieu K. Mar 14 '17 at 17:15
  • Read this https://codahale.com/a-lesson-in-timing-attacks/ and this https://news.ycombinator.com/item?id=761059 thoroughly to understand the difference. – Shayan Jun 17 '22 at 09:18

6 Answers6

33

Updated answer:

Apologies, I missed the word "logical" in your question even though it is there. (I've taken the liberty of emphasizing it a bit with an edit.)

Consider the case where you want any side-effects to always occur, regardless of whether the left-hand expression evaluates true or false. E.g., contrast:

if (foo() & bar()) {
    // Only call this if both operations returned true
}

with

if (foo() && bar()) {
    // Only call this if both operations returned true
}

Let's assume both foo and bar have effects that we want to have happen regardless of whether foo returns true or false. In the first one above, I know that bar will always get called and have its effect. In the latter, of course, bar may or may not get called. If we didn't have the non-short-circuit version, we'd have to use temporary variables:

boolean fooResult, barResult;
fooResult = foo();
barResult = bar();
if (fooResult && barResult) {
    // ...
}

You might argue (I probably would) that you should do that anyway, because it's way too easy to misread if (foo() & bar()), but there we go, a pragmatic reason for having non-short-circuit versions.

Original answer:

How would you propose & (or |) be a short-circuited operator? With && and ||, it makes sense because you're dealing with boolean conditions: They can be true or false, there are no shades of grey. But & and | deal with bits, not booleans. The result is a number. I mean, I guess & could not evaluate the right-hand side if the left-hand side were 0, and similarly | could not evaluate it if the left-hand side were all-bits-on for whatever the type was, but I don't see much point to making the one edge case of each operator significant (as compared to the 254 or more other cases).

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • 3
    In Java & and | does not work with bits if applied to boolean type. – Suzan Cioc Feb 13 '12 at 17:41
  • Sorry, I would remove downvote if I can. I just tried it because you were wrong, aren't you agree? :> – Suzan Cioc Feb 13 '12 at 18:14
  • @SuzanCioc: Thanks, I had skimmed right over the word "logical" in the question! Updated the answer and edited the question to help others avoid the same mistake. – T.J. Crowder Feb 13 '12 at 18:26
  • There are, in fact, efficiency reasons for not short-circuiting: branching can be expensive, and if both conditions are cheap, it can actually be _faster_ to use `&` and `|`. I wouldn't recommend it unless a) you're really really keen on performance, and b) you can produce benchmark data to support you. – Louis Wasserman Feb 13 '12 at 19:21
  • Relying on `non-short-circuit` logic(especially not everywhere, but in some places) seems like a flaw in code design for me. It makes you keep in mind the fact that all elements of expression will have its effect. – Nikita Barishok Apr 13 '18 at 11:08
16

There are instances where the components of a boolean expression involve operations that you'd want to have executed in all cases. Consider the following example of checking a password for validity:

while ( !password.isValid() & (attempts++ < MAX_ATTEMPTS) ) {

    // re-prompt

}

If the second condition was not evaluated due to short-circuiting, attempts would never be incremented. Thus greater programmer flexibility is enabled.

calebds
  • 25,670
  • 9
  • 46
  • 74
2

My case (C++):

void setFields(Parameters bundle)
{
  if (setIfDifferent(&field1, bundle.value1) | 
      setIfDifferent(&field2, bundle.value2) |
      setIfDifferent(&field3, bundle.value3)) {
    storeState();
  }
}

setIfDifferent() sets the object's field with new value if they differ, in which case it returns true; or it returns false in case the field's and the new value are the same. So, we want to try to set all fields, and if any of them changed, then we want to store new object's state.

Alex Che
  • 6,659
  • 4
  • 44
  • 53
1

You can have some side-effects in logical expression, for example you can assign simultaneously with checking. This may work wrongly if only one part evaluated.

Can't remember good example now, but remember that I was in need of "non-short-circuit" operators sometimes.

Hmmm.... Below is WRONG example, which won't work without "non-short-circuit" OR:

if( (object1=getInstance1()).getNumber() == 1 || (object2=getInstance2()).getNumber() == 2 ) {

    // do something which requires bot object1 and object2 assigned

}
Suzan Cioc
  • 29,281
  • 63
  • 213
  • 385
0

In my case, I have two methods that compare two different but related objects (Object2 is an attribute of Object1) to see if there were any changes. An update needs to happen if either are updated, but both need to be evaluated so that the objects will be modified if both have been changed. Therefore, a single pipe "OR" comparison is required.

EX:

if (compare(object1, currentObject1) | comparison(object2, currentObject2)) {
    updateObject1(object1);
}
0

Technically, & and | are not logical, they're bitwise operators that become logical operators when associated with booleans.

There are times when you'd want to include assignment expressions inside your logical expressions.

Say:

if(a = (checkForSomeCondition()) | b = checkForAnotherCondition())
{
 //now do something here with a and b that has been cached
}

If I had used ||, I'd not be able to perform the above check and would have had to split the assignments into separate statements. I've never come across scenarios like this during application development, but come across it a few times while writing algorithms.

Of course, you could use unary operators on the logical expressions or pass variables by reference into a predicate, but those seem like less common cases than the above.

arviman
  • 5,087
  • 41
  • 48