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

As already pointed out by others, no matter what gets pass into the function as the two arguments, it gets evaluated as it gets passed in. That is way before the tenary operation.

On the other hand, this

#define sc_and(a, b) \
  ((a) ?(b) :0)

would "short-circuit", as this macro does not imply a function call and with this no evaluation of a function's argument(s) is performed.


When the statement

bool x = a && b++;  // a and b are of int type

executes, b++ will not be evaluated if the operand a evaluated to false (short circuit behavior). This means that the side-effect on b will not take place.

Now, look at the function:

bool and_fun(int a, int b)
{
     return a && b; 
}

and call this

bool x = and_fun(a, b++);

In this case, whether a is true or false, b++ will always be evaluated1 during function call and side effect on b will always take place.

Same is true for

int x = a ? b : 0; // Short circuit behavior 

and

int sc_and (int a, int b) // No short circuit behavior.
{
   return a ? b : 0;
} 

1 Order of evaluation of function arguments are unspecified.


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