Is There an Non-Short Circuited Logical "And" in C++

Is there an Non-Short circuited logical and in C++?

The & operator performs logical "and" operation for bool operands and is not short circuited.

It's not a sequence point. You cannot rely on the order of evaluation of the operands. However, it's guaranteed that both operands are evaluated.

I do not recommend doing this. Using temporary variables is a better solution. Don't sacrifice readability for "clever code".

In C, is single & and single | valid so as to avoid short circuit? Also please give some examples of utility of same in C#

Here are the answers to your questions:

Is & and | valid in C so that short circuit can be avoided?

No. The & and | operators in C mean different things compared to their C# logical counterparts.

In C, & and | are bitwise operators. They will evaluate both the sides and combine the bits of the resulting values according to the operator. Afterwards, if the resulting value is used in a logical context it will be processed as 0=false, everything else=true.

This is not the same as short-circuit logical operators as C# have.

In C# bool can only be true, false or null. Unlike C 0 is not false and all non-zero value is not true. So short circuit can never take place in C#.

So in C# what is the utility of & and |?

The purpose of & and | as logical operators in C# is to support non-short-circuit evaluation.

Take this example:

// s is string
if (s != null && s.Length > 0) { ... }

Here, if s is indeed null, the value of the first operand is false, hence the whole expression can never be true and thus the second operand, s.Length > 0 is not evaluated.

Contrast to this:

if (s != null & s.Length > 0) { ... }

Observe that I switched to the non-short-circuit & operator here. Here, if s is null, both operands will still be evaluated and the code will throw a NullReferenceException.

In some situations, it may be beneficial and required that you evaluate both sides even if you know the result will never be false regardless of what the second operand says. In those situations, you would use the non-short-circuit operators.


In C, the operators mean this:

  • | = bitwise OR operator
  • & = bitwise AND operator
  • || = logical OR operator that short circuits
  • && = logical AND operator that short circuits

In C#, the operators mean this:

  • | = bitwise OR operator if applied to integers, logical non-short-circuit OR operator if applied to bools
  • & = bitwise AND operator if applied to integers, logical non-short-circuit AND operator if applied to bools
  • || = logical OR operator that short circuits
  • && = logical AND operator that short circuits

Why is this version of logical AND in C not showing short-circuit behavior?

This is a trick question. b is an input argument to the sc_and method, and so will always be evaluated. In other-words sc_and(a(), b()) will call a() and call b() (order not guaranteed), then call sc_and with the results of a(), b() which passes to a?b:0. It has nothing to do with the ternary operator itself, which would absolutely short-circuit.

UPDATE

With regards to why I called this a 'trick question': It's because of the lack of well-defined context for where to consider 'short circuiting' (at least as reproduced by the OP). Many persons, when given just a function definition, assume that the context of the question is asking about the body of the function; they often do not consider the function as an expression in and of itself. This is the 'trick' of the question; To remind you that in programming in general, but especially in languages like C-likes that often have many exceptions to rules, you can't do that. Example, if the question was asked as such:

Consider the following code. Will sc_and exibit short-circuit behavior when called from main:

int sc_and(int a, int b){
return a?b:0;
}

int a(){
cout<<"called a!"<<endl;
return 0;
}

int b(){
cout<<"called b!"<<endl;
return 1;
}

int main(char* argc, char** argv){
int x = sc_and(a(), b());
return 0;
}

It would be immediately clear that you're supposed to be thinking of sc_and as an operator in and of itself in your own domain-specific language, and evaluating if the call to sc_and exhibits short-circuit behavior like a regular && would. I would not consider that to be a trick question at all, because it's clear you're not supposed to focus on the ternary operator, and are instead supposed to focus on C/C++'s function-call mechanics (and, I would guess, lead nicely into a follow-up question to write an sc_and that does short-circuit, which would involve using a #define rather than a function).

Whether or not you call what the ternary operator itself does short-circuiting (or something else, like 'conditional evaluation') depends on your definition of short-circuiting, and you can read the various comments for thoughts on that. By mine it does, but it's not terribly relevant to the actual question or why I called it a 'trick'.

Short-circuiting of non-booleans

The second expression will evaluate to either 1 or 0.

Quoting the C11 standard draft:

6.5.14 Logical OR operator


  1. The || operator shall yield 1 if either of its operands compare unequal to 0; otherwise, it yields 0. The result has type int.

So the two expressions are very different, since one of them yields a pointer, and the other one an integer.

Edit:

One of the comments claims that this answer is only valid for c, and @Lightness Races in Orbit is right.

There are also answers that are only correct for c++1, although the only difference with them is that c++ has type bool and then it evaluates this expression as bool instead of int. But apparently there is an important issue with overloading || operator in c++, which prvents short-citcuiting to apply for the object that overloads it.

So for c++ there are more things to consider, but since this question was tagged with both languages tags, then it's necessary to mention at least the differece.

The rule still applies when short-circuiting applies, i.e. the result of the evaluation of the expressions is either 1 or 0 for c and true or false for c++.


1 Like these answers: 1, 2

Short circuit vs non short circuit operators

One reason you might want to use the non-short-circuiting operator is if you are somehow depending on side-effects of functions. For example.

boolean isBig(String text) {
System.out.println(text);
return text.length() > 10;
}

...
if( isBig(string1) || isBig(string2) ){
...
}

If you don't care about whether the println is executed then you should use the short circuit operations as above. However, if you want both strings to be printed always (thus depending on side effects) then you need to use the non-short-circuit operator.

Practically speaking, you almost always want to use the short-circuit operators. Relying on side effects in expressions is usually bad programming practice.

One exception is in very low level or performance-sensitive code. The short-circuiting operators can be slightly slower because they cause branching in the program execution. Also using bitwise operators allows you to do 32 or 64 parallel boolean operations as a single integer operation, which is very fast.

Is short-circuiting logical operators mandated? And evaluation order?

Yes, short-circuiting and evaluation order are required for operators || and && in both C and C++ standards.

C++ standard says (there should be an equivalent clause in the C standard):

1.9.18

In the evaluation of the following expressions

a && b
a || b
a ? b : c
a , b

using the built-in meaning of the operators in these expressions, there is a sequence point after the evaluation of the first expression (12).

In C++ there is an extra trap: short-circuiting does NOT apply to types that overload operators || and &&.

Footnote 12: The operators indicated in this paragraph are the built-in operators, as described in clause 5. When one of these operators is overloaded (clause 13) in a valid context, thus designating a user-defined operator function, the expression designates a function invocation, and the operands form an argument list, without an implied sequence point between them.

It is usually not recommended to overload these operators in C++ unless you have a very specific requirement. You can do it, but it may break expected behaviour in other people's code, especially if these operators are used indirectly via instantiating templates with the type overloading these operators.

Reason for the existence of non-short-circuit logical operators

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).

What is short-circuit evaluation in C?

The && operator uses lazy evaluation. If either side of the && operator is false, then the whole expression is false.

C checks the truth value of the left hand side of the operator, which in your case is 0. Since 0 is false in c, then the right hand side expression of the operation, (a = b = 777), is never evaluated.

The second case is similar, except that || returns true if the left hand side expression returns true. Also remember that in c, anything that is not 0 is considered true.

Hope this helps.

Is there logical short-circuiting in the C preprocessor?

Very simple: undefined macros have numeric value zero, and division by zero is illegal.

#if FIXEDSIZE && CHUNKSIZE/FIXEDSIZE > 42
#define USE_CELLPOOL
#endif

#if does evaluate the rest of its line as an integer constant expression. Your linked documentation begins:

The ‘#if’ directive allows you to test the value of an arithmetic expression, rather than the mere existence of one macro.

That isn't a gcc extension, the Standard's syntax for #if is

#ifconstant-expression new-line groupopt.

The C99 preprocessor treats all constants as [u]intmax_t.

Does C use short circuit evaluation even when arguments are function calls?

Yes, the functions are not called if root1->data == root2->data is false.

Simple check is to do this:

#include <unistd.h>
#include <stdlib.h>

int main(void)
{
write(1, "z", 1);
if ((1 == 0) && write(1, "a", 1) && write(1, "b", 1))
{
write(1, "c", 1);
}
write(1, "d", 1);
return (EXIT_SUCCESS);
}


Related Topics



Leave a reply



Submit