-5

&& 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


Concept of ""Short Circuit" in C

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 -

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

  2. 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 |?

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
puregeek
  • 175
  • 3
  • 9
  • 5
    OMG that's a lot of text. Why would you ever want to "avoid" short-circuiting? It's a *good* thing to have! – unwind Dec 21 '17 at 14:09
  • 5
    You really don't have to explain how C# works to the veteran C# programmers here, I think they are quite aware. – Lundin Dec 21 '17 at 14:10
  • 1
    Short-circuiting in C# is definitely a thing that is both useful and works fine, try evaluating methods in the two branches. – Lasse V. Karlsen Dec 21 '17 at 14:10
  • In C, `|` and `&` are *bit-wise* operators, whereas `||` and `&&` are *logical* operators. This is different from C#. – Lasse V. Karlsen Dec 21 '17 at 14:11
  • Answer: in C, the `|` and `&` have unspecified order of evaluation. They do not "short-circuit". But they also don't mean the same thing as `||` and `&&`, because they are bit-wise versus logical operators. – Lundin Dec 21 '17 at 14:12
  • IMO this question is more than twice as long as it actually needs to be. –  Dec 21 '17 at 14:13
  • @LasseVågsætherKarlsen How is this different from C#? They are bitwise and logical operators there as well. – Daniel Hilgarth Dec 21 '17 at 14:13
  • In C, `|` is a bitwise operator. In C#, `|` is a bitwise operator if applied to integers, logical if applied to bools. Same difference for `&`. – Lasse V. Karlsen Dec 21 '17 at 14:14
  • @LasseVågsætherKarlsen Right. I even wrote that once in an answer: https://stackoverflow.com/a/7331721/572644 – Daniel Hilgarth Dec 21 '17 at 14:16
  • There have been multiple rather lively discussions in comment threads on Stack Overflow about how `|` and `||` differ and what they can be used for so contrary to what @Lundin said, not *all* C# programmers know about this. – Lasse V. Karlsen Dec 21 '17 at 14:17
  • When int cannot be evaluated is bool in C# and hence logical operations can't be performed, why & and | is present? And if present to avoid short circuit, how short circuit can occur? – puregeek Dec 21 '17 at 14:18
  • `if (a() && b())` is different from `if (a() & b())`. If `a()` returns `false`, `b()` will not be called and evaluated in the first example, but will be called and evaluated in the second. – Lasse V. Karlsen Dec 21 '17 at 14:19
  • And so you are saying that in C also & and I can be used and as a result short circuit can be avoided? – puregeek Dec 21 '17 at 14:20
  • No, in C `&` and `|` are **bitwise** operators, they don't deal with logical results at all, hence talking about short-circuit boolean evaluation here is irrelevant. – Lasse V. Karlsen Dec 21 '17 at 14:20
  • @LasseVågsætherKarlsen I only said "veteran C# programmers", not the rest of them :) Preferably one of the former should answer this question. Me, I only got lured here by the C tag. – Lundin Dec 21 '17 at 14:20
  • "Basically, the purpose of the &, | and ^ operators is not to do logical tests in C, its just that the language is type-unsafe enough to allow this as a side-effect." as said by @AdamBrown, so let be as a side effect, it is do functioning in C? – puregeek Dec 21 '17 at 14:22
  • [sigh] just code so that it does not matter... – Martin James Dec 21 '17 at 14:23
  • 1
    This comment thread serves no use right now. Read up on the documentation for both C and C# and you will find everything is pretty well documented. – Lasse V. Karlsen Dec 21 '17 at 14:24
  • @puregeek often the purpose of &, | and ^ operators in C is to do up to 64 logical tests in parallel. – Pete Kirkham Dec 21 '17 at 14:24

3 Answers3

3

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
Community
  • 1
  • 1
Lasse V. Karlsen
  • 380,855
  • 102
  • 628
  • 825
1

The single-character operators & and | are bitwise AND and OR, respecitvely. They have nothing to do with boolean tests, for which the short-circuiting && and || are used.

I don't quite see the point of your questions:

  1. They are "valid", they are C operators, but their use is not for boolean logic, they are for computing binary results.
  2. In C# they seem to serve dual purposes, described as "Integer bitwise AND, Boolean logical AND" in the operators documentation. But I don't use C#.
unwind
  • 391,730
  • 64
  • 469
  • 606
  • In C# `|` and `&` are non-short-circuit boolean operators **and** bitwise operators (just as they are in C), so these operators have dual meaning depending on the types involved. That is, to clarify, if the operators are used on integers they're bitwise, if they're used on bools they're logical. – Lasse V. Karlsen Dec 21 '17 at 14:12
0

& and | are not logical operators. Using them as logical operators takes advantage of the C language feature that zero is false and non-zero is true (which is not fully type safe).

C# is a fully type safe language, so logical expressions must be boolean. This means that logical operators will only work on booleans (&&, ||) whereas bitwise operations only work on integral types (&, |, ^)

Basically, the purpose of the &, | and ^ operators is not to do logical tests in C, its just that the language is type-unsafe enough to allow this as a side-effect.

EDIT: I stand corrected, (&, |) are also apparently valid logical operators in C# (just shorthand for &&, ||)

Adam Brown
  • 1,667
  • 7
  • 9
  • 2
    Though in C# both `&` and `|` are also logical operators, non-short-circuit logical operators, if applied to bools. They're bitwise if applied to integers. – Lasse V. Karlsen Dec 21 '17 at 14:13
  • 1
    `|` and `&` are not short-hand for `||` and `&&` respectively. If you know C, stick to answering for C :) `|` and `||` mean different things. The same underlying operation, logical OR, but the exact behavior is different so you can't save a character in your code by omitting one of those characters and keep the current behavior. As such they're not short-hand. – Lasse V. Karlsen Dec 21 '17 at 14:21
  • C does allow `& | ^ ~` for boolean operands, because how else would you set the bit(s) of a boolean? :) As it turns out, C will actually implicitly promote the bool operands to `signed int`. So that code like `~false` actually gives you a negative result. Happy days. – Lundin Dec 21 '17 at 15:01