C++ boolean evaluation order question.

Hi computer geeks! I’m sure someone will be able to answer this:

In C++, if I have the statement

if(x && y)

and x is false, is y evaluated? If it is, I’ll have to switch to


which is totally nasty (but maybe exactly the same as far as the compiler is concerned).


Why would you even need y evaluated? Once x has been determined to be false, the expression is false. End of story.

No, the second argument in a && will not be evaluated if the first argument is false. Likewise, the second argument in a || will not be evaluated if the first argument is true.

So things like:
if (x != 0 && 1/x > 1000) { }
if (x == 0 || 1/x > 1000) { }

will not give you a divide by zero error if x is zero.

This is called Short Circuit Evaluation, also the reason most people will tell you not to overload those two operators.

Thanks Algorithm! I remember being told this, but not which languages/schemes it applied to.

That’s exactly the point. If y DOES get evaluated, I’m screwed. Suppose A is an array with 5 elements:

while(i<5 && A*>0){

If there is no short circuit evaluation, A[5] will be accessed. Since A[5] doesn’t really exist, I’ll get a segmentation fault and my program will die.

I’ve never used a language that didn’t handle that correctly without blowing up. C++, Perl, PHP, Pascal, BASIC, and Java all seem to deal with that situation that way. It’s never been an issue, so I’ve never really given it any thought. Anyone know of any that bomb in that situation?

Not quite end of story.

If we allow for the possibility that x and y are placeholders for more complicated expressions, then sometimes you might need to have both evaluated even if the results of the test can be determined just by looking at x.

For example, suppose that the expression were really
if (function1(a,b) && function2(a,b))
Now let us also suppose that function2 has side-effects. For example, it might increment a hidden counter, or write an entry out to a log file. Or maybe function2 alters the value of one of its parameters (possible if they are passed by reference). In that sort of situation, it might be critical for you to know that the side-effect takes place no matter what function1(a,b) returns. In that case, you would write the statement as
if (function1(a,b) & function2(a,b))
just to guarantee that both terms of the “and” condition will be evaluated.

That’s one of the major reasons why C++ (and C before it) had both the short-circuit and symmetric forms of the boolean operators.

Now, it is often argued that side effects like the ones I described above are a bad programming practice. But, in a very real sense, that battle has been lost with the advent of object-oriented programming, where almost all state changes are accomplished via function side effects.

The upshot is that you have to pay attention to what the expressions on each side of a boolean operator actually do, and then decide whether or not short-cicuit evaluation is appropriate or not. Short-circuiting is probably what you want 98% of the time. But it’ll kill your program the remaining 2% of the time.

There are also some unusual situations where short-circuit evaluation may actually slow the program down by reducing the options available to the code optimizer for re-ordering expression evaluations. And in some architectures with fine-grain parallel execution, it might be faster to always evaluate the two conditions in parallel than to wait on evaluating the second until the first one has been completely evaluated.

The Pascal standard actually prohibited short-circuit evaluation, so KarmaComa’s code would be a problem in that language. As far as I know, there is no definitive standard saying what Basic would do. The other languages you mention do feature short-circuit evaluation.

MS Visual Basic. I didn’t bother to test .NET, but VB6 and earlier did not short-circuit. KarmaComa’s code would throw a subscript-out-of-range error.

I’ve also done work in Old and New Fortran, and I’m loath to trust either one with anything :smiley:

Even ignoring the issue of short-circuit evaluation, those are logically different due to the fact that truth is indicated by any nonzero value, not simply “1”. The first is equivalent to:
if ( (function1(a,b) != 0) && (function2(a,b) != 0) )
whereas the second is equivalent to
if( (function1(a,b) & function2(a,b)) != 0 )

So if function1 returns 5 and function2 returns 10, the original test (5 && 10) succeeds, whereas the alternate (5 & 10) fails.

I’m sure you realize this, but I just wanted to point it out. I’m not sure which is more repulsive – relying on the side effects of the tests or trying to use a bitwise AND like a logical AND. :slight_smile:

IIRC, in .NET you have to use “AND ALSO” or “OR ELSE” (rather than just “AND” or “OR”) in order to get it to stop after the first false condition. Don’t think there’s any way around it VB6, it will evaluate all of them even if the first one is false.

This may not be true any longer (or of less consequence), since C++ has a proper bool type that can only be true or false, and the data type of a boolean expression is now bool, with appropriate promotion to int where applicable.

In this case, the bitwise AND behaves identically to a logical AND except for short-circuiting.

But you should definitely be aware of the consequences of bitwise AND ( & ) in any event since much code depends on the value of ints as conditions. Failure to understand integral promotion and the & operation on integers could lead to some insidious bugs as ntucker points out.

I personally never use & to indicate a ‘short-circuit-less’ logical AND (wayyyyy too dangerous in my opinion), but you might consider me biased coming from a C background.

Really? When did this come about?

Geez, I dunno, it’s in the 1998 language spec, but I suspect it’s been in there a lot earlier than that. I’ve only just recently started using it (again, C background, have to ‘unlearn’ using ints). I’m using Visual C++ 5 at work at present, and its got the bool type.

Sorry, don’t know when it was added formally to the language. But it’s been a long time.

The BOOL data type has been around since at least '93 when I first took up C++ programming, using Borland Turbo C++.

Nitpick: Mm, but it’s not the BOOL data type, capitalized. Many compilers custom defined this, or had a header file that typedef’d this to int. It is a proper bool data type, lowercase, with lowercase true and false as its only values (and couldn’t be forced to take any other value).

OK, I thought it was something new. The problem with that is that a statement like ‘bool b = 2;’ will get you nothing but a warning in Visual C++ 6, which is a fairly popular compiler.

Visual C++ has never been reliably ‘standard’. Evidently 7.1 (.NET) made major improvements.


bool b=2;

should be stronger than a warning, but:

bool b=(bool)2;

or the more C++

bool b=static_cast< bool >(2);

are both reasonable as a forced integer cast.

VS.NET 2003 let me off with the same warning.

How annoying.