BuckFilledPlatypus
BuckFilledPlatypus

Reputation: 2178

How an 'if (A && B)' statement is evaluated?

if( (A) && (B) )
{
  //do something
}
else
  //do something else

The question is, would the statement immediately break to else if A was FALSE. Would B even get evaluated?

I ask this in the case that B checking the validity of an array index say array[0] when the array is actually empty and has zero elements. Therefore throwing a segfault because we are trying to access something that is out of bounds of the array. Specifically

if( (array.GetElements() > 0) && (array[0]))
  array[0]->doSomething();
else
  //do nothing and return

This may be dangerous if array[0] actually gets evaluated because it segfaults without the first check to the left of the '&&'. Precedence tells me that the left side will definitely take precedence but it doesn't tell me that it won't evaluate the right side if the left is FALSE.

Upvotes: 20

Views: 127522

Answers (8)

Gabriel Staples
Gabriel Staples

Reputation: 53055

For the case where A and B are both integers, floating point types, or pointers:

What does while (a && b) do when a and b are both integers, floating point types, or pointers?

AKA: rules of integers or other numbers being cast to bools.

Short answer

When a and b are both integers, floating point types, or pointers, writing while (a && b) is equivalent to while ((bool)a && (bool)b), and whenever you cast an one of these types to a bool, zero is false and everything else is true.

If (bool)a is false (value zero), then it stops evaluating early, since certainly a && b cannot be true if the first part of that test is false.

When does "contextual conversion to bool" apply?

This concept applies to if, for, while, and do { } while blocks, not just while. It applies to !, ||, and && operators. The operands in such expressions are "said to be contextually converted to bool".

See here:

  1. @MSalters' comment. Thank you.
  2. https://en.cppreference.com/w/cpp/language/implicit_conversion and search for "contextually converted to bool". This source says that the "contextual conversion to bool" occurs for all of the following situations:
    1. the controlling expression of if, while, for
    2. the operands of the built-in logical operators !, && and ||
    3. the first operand of the conditional [ternary] operator ? :
    4. the predicate in a static_assert() declaration
    5. the expression in a noexcept specifier
    6. the expression in an explicit specifier (since C++20)

Details

while (a && b) is exactly equivalent to while ((bool)a == true && (bool)b == true), which is also exactly equivalent to while (a != 0 && b != 0) or (same thing): while (a != false && b != false).

Those can be read as: "while integers, floating point types, or pointers a and b are both true when cast to bool", or as: "while integers, floating point types, or pointers a and b are both non-zero."

I think most people prefer the while (a && b) form, however, since it's the shortest and still easy to read.

The key takeaway is:

These all mean and do the same thing:

int a = 2;
int b = 3;
// // or
// float a = 2.0;
// float b = 3.0;
// // or 
// int* a = (int*)0x11223344UL;
// int* b = (int*)0xaabbccddUL;
// // etc.

// these are all **equivalent**!:

// 1. "true"-based forms
while (a && b) {};              // shortest and most-often used version
while ((bool)a && (bool)b) {};  // most-explicit and clear version
while ((bool)a == true && (bool)b == true) {};
while (((bool)a == true) && ((bool)b == true)) {};

// 2. "false"-based forms (these all are exactly equivalent to the "true"-based
// forms above)
while (a != 0 && b != 0) {};
while ((a != 0) && (b != 0)) {};
while (a != false && b != false) {};

// etc.

The following, however, are NOT the same as the examples above:

while (a == true && b == true) {};
while ((a == true) && (b == true)) {};

This is because true is defined strictly as 1 (and false is defined strictly as 0). Therefore, even though a == 1 is false when a is 2, (bool)a == 1 is true when a is any non-zero integer, including 2.

Note: this answer has been completely rewritten and fixed for correctness, and moved to here from this now-deleted question here: What does while (a && b) do when a and b are both integers? [duplicate]. That question was deleted under the premise it was a duplicate of this question, hence why I moved my answer to here.

Upvotes: 0

Kumaran P
Kumaran P

Reputation: 1

Even in python short circuiting happens

a = []
if 0 and a[0]:  # short circuit happens
    print("short circuit")
if 1 and a[0]:  # we get IndexError: list index out of range exception
    print("this will not be evaluated")

Upvotes: -2

Gokul
Gokul

Reputation: 9

i will try to clear it as much as possible consider this below example:

#include <stdio.h>
void main()
{
  int a= 1;
  int b = 0;
  if(a && b++)
  printf("%d  %d",a++,b);
  
  printf("%d  %d",a,b);
}

Output 1 1

now the same code with a = 0;

#include <stdio.h>
void main()
{
  int a= 0;
  int b = 0;
  if(a && b++)
  printf("%d  %d",a++,b);
  
  printf("%d  %d",a,b);
}

Output : 0 0

as you can clearly see inside a if condition with &&(and) operation if the first argument is 0 then no matter what the value of b is this condition will fail so the second operator b wont even get executed.

with that being said if instead of && we kept ||(OR) then the result would be diff

#include <stdio.h>
void main()
{
  int a= 0;
  int b = 0;
  if(a || b++)
  printf("%d  %d",a++,b);
  
  printf("%d  %d",a,b);
}

Output: 0 1

because now even though a was 0 there is still a chance be could be 1 and thus the compiler executes the line.

Upvotes: -1

Prasad Shinde
Prasad Shinde

Reputation: 9

for logical && both the parameters must be true , then it ll be entered in if {} clock otherwise it ll execute else {}. for logical || one of parameter or condition is true is sufficient to execute if {}.

if( (A) && (B) ){
     //if A and B both are true
}else{
}
if( (A) ||(B) ){
     //if A or B is true 
}else{
}

Upvotes: -1

Gavin H
Gavin H

Reputation: 10502

Yes, it is called Short-circuit Evaluation.

If the validity of the boolean statement can be assured after part of the statement, the rest is not evaluated.

This is very important when some of the statements have side-effects.

Upvotes: 4

strager
strager

Reputation: 90042

You are asking about the && operator, not the if statement.

&& short-circuits, meaning that if while working it meets a condition which results in only one answer, it will stop working and use that answer.

So, 0 && x will execute 0, then terminate because there is no way for the expression to evaluate non-zero regardless of what is the second parameter to &&.

Upvotes: 12

michael pearson
michael pearson

Reputation: 684

yes, if( (A) && (B) ) will fail on the first clause, if (A) evaluates false.

this applies to any language btw, not just C derivatives. For threaded and parallel processing this is a different story ;)

Upvotes: -6

John Millikin
John Millikin

Reputation: 200916

In C and C++, the && and || operators "short-circuit". That means that they only evaluate a parameter if required. If the first parameter to && is false, or the first to || is true, the rest will not be evaluated.

The code you posted is safe, though I question why you'd include an empty else block.

Upvotes: 51

Related Questions