&&
is logical AND and ||
is Logical OR
In C#, for example,
using System;
class Program {
static void Main() {
Console.WriteLine("Enter a number");
int num = int.Parse(Console.ReadLine());
if(num>=0&&num<=10)
Console.WriteLine("Hi");
else
Console.WriteLine("Hello");
}
}
Now for &&
only if both the conditions are true, then the if
block gets executed, else else
block gets executed.
So for input 2
conditions num>=0
and num<=10
are both true
. So condition num>=0&&num<=10
is true
and if
statement gets executed. get output Hi
.
For input -2
condition num<=10
is true
but condition num>=0
is false
. Since both the conditions should be true, condition num>=0 && num<=10
is false so instead of for
statement else
statement gets executed. So the output is Hello
.
For input 12
condition num>=0
is true
but condition num<=10
is false
. Since both the conditions should be true, condition num>=0 && num<=10
is false so instead of for
statement else
statement gets executed. So the output is Hello
.
Now, in this case if the first condition num>=0
comes out to be flase
compiler does not check the second condition num<=10
, since in case of &&
if both the conditions are true
, only then num>=0&&num<=10
is true
.
Now consider the following program -
using System;
class Program {
static void Main() {
Console.WriteLine("Enter a number");
int num = int.Parse(Console.ReadLine());
if(num>=0&num<=10)
Console.WriteLine("Hi");
else
Console.WriteLine("Hello");
}
}
Here instead of &&
, &
is given
The output will be same as the truth table for &&
and &
are same.
But here, during evaluation of the condition num>=0&num=<10
, if the input is -2
, then first condition num>=0
is false
. But unlike &&
even after first condition is false
second condition num<=10
is evaluated, and then the control passes on to the next statement.
Similarly for logical OR; consider the following C# example -
using System;
class Program {
static void Main() {
Console.WriteLine("Enter a number");
int num = int.Parse(Console.ReadLine());
if(num<=0||num>=10)
Console.WriteLine("Hi");
else
Console.WriteLine("Hello");
}
}
If input is -2
, first condition num<=0
is true
and second condition num>=10
is false
. Since in ||
num<=0||num>=10
is true
if either of the two statements are true
, so if
block gets executed and the ouput is Hi
.
If input is 12
first condition num<=0
is false
but second condition num>=10
is true
. For ||
num<=0||num>=10
is true
if either condition is true
, so if
block gets executed and the output is Hi
.
If input is 2
first condition num<=0
is false
. Also second condition num>=10
is false. Since both the conditions are false
num<=0||num>=10
is flase
and else
block gets executed. So output is Hello
.
Now consider the following program -
using System;
class Program {
static void Main() {
Console.WriteLine("Enter a number");
int num = int.Parse(Console.ReadLine());
if(num<=0|num>=10)
Console.WriteLine("Hi");
else
Console.WriteLine("Hello");
}
}
Here instead of ||
|
is used. Both the programs generate same output as truth tables of ||
and |
are same.
But when ||
is used and if input is -2
, first condition num<=0
is true
. Since for num<=0||num>=10
to be true
either conditions needs to be true
and first condition num<=0
is already true, compiler doesn't check the second condition num>=10
But when |
is used and here also the input is -2
, even after evaluating the first condition num<=0
to be true, compiler checks the second condition num>=10
Let us consider the following example -
#include <stdio.h>
int main() {
int a, b, c;
a = -1;
b = 0;
c = ++a && ++b;
printf("a = %d, b = %d, c = %d\n", a, b, c);
return 0;
}
Expected output:
a = 0, b = 1, c = 0
Real output:
a = 0, b = 0, c = 0
It is because in the statement c = ++a && ++b;
when the value of a
is incremented by 1
it's new value is 0
. 0
is evaluated to be false
. In &&
the whole condition is false
if either the first condition or second condition is false
. So here as ++a
is evaluated to be false
the condition ++b
is never checked by the compiler. So b
is never incremented and its value stays 0
Now consider the following example -
#include <stdio.h>
int main() {
int a, b, c;
a = 0;
b = 10;
c = ++a || ++b;
printf("a = %d, b = %d, c = %d\n", a, b, c);
return 0;
}
Expected output:
a = 1, b = 11, c = 1
Real output:
a = 1, b = 10, c = 1
Here in the statement
c = ++a || ++b;
++a
is 1
and 1
is evaluated as true
. In ||
the whole condition is true
if either the first condition or second condition is true
. Here since first condition ++a
is true, second condition ++b
is never checked by the compiler. So the value of b
is never incremented and stays 10
.
Now, my question -
Is &
and |
valid in C so that short circuit can be avoided?
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 |
?
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 circuitsIn 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