views:

127

answers:

3

Possible Duplicate:
What is the diffference between the | and || or operators?

Logical AND and OR:

(x & y)
(x | y)

Conditional AND and OR:

(x && y)
(x || y)

I've only known about conditional operands up to this point. I know what it does and how to apply it in if-statements. But what is the purpose of logical operands?

+6  A: 
(x && y) 

is lazy. It will only evaluate y if x is true.

(x & y)

is not lazy. y will always be evaluated.

Robert Harvey
This is flat wrong I believe? Can you cite? ( I agree with the first assertion, but not the second)
John Weldon
That's only half the story, and arguably the less important half.
Kennet Belenky
spender
could whoever is upvoting this post explain? this seems very wrong.
John Weldon
@John, it's absolutely correct. When operating on booleans, the only difference is "laziness". Effectively the operation is no different whether operating on booleans or larger integral types. It's doing a bitwise on two single bits and returning a bit.
spender
@John That is flat true. From the C# Spec in Section 7.10.3 Boolean logical operators: "The result of x | y is true if either x or y is true. Otherwise, the result is false." Also see Section 7.11 Conditional logical operators: "The operation x || y corresponds to the operation x | y, except that y is evaluated only if x is false." .
Michael Stum
@John: here is a reference. http://steve-fair-dev.blogspot.com/2007/02/c-lazy-or-full-boolean-evaluation.html
Robert Harvey
Yes, but the question is about the operators in general not as they apply to *one* type (bool)
John Weldon
@Robert, I concede that reference in relation to *booleans*. Surely you agree that the question is more broad than that?
John Weldon
@John, for the second, y will always be evaluated regardless of type.
Matthew Flaschen
Meh. I think I'll go answer some other questions.
Robert Harvey
I absolutely agree about the short-circuit. It's just irrelevant when comparing bitwise vs. logical operators.
John Weldon
Matthew Flaschen
@Michael; I explicitly stated that I agreed with the fact that the double operator is a short-circuit operator... my real concern is that if you compare logical and bitwise operators (on all types, not a subset), short circuit evaluation is not relevant.
John Weldon
@John: I'm pretty sure that short-circuiting is the primary reason one chooses conditional over bitwise operators.
Anon.
@Anon; and that could be the cause of all the disagreement. It doesn't factor as an important reason to me. Maybe for some people it does. The risk is that choosing a bitwise comparison blindly because it doesn't short-circuit could lead to confusing results if one doesn't realize that it's in fact a bitwise operation.
John Weldon
@John: Indeed, I do feel that this post is lacking and only really answers half the question. And I feel the same about the accepted answer.
Anon.
@Anon, @Michael, @Robert, @Matthew; Updated my answer after reading the spec.
John Weldon
Michael Stum
@Michael; makes sense... my info was misleading. @Robert, it appears SO isn't letting me remove my downvote... My apologies.
John Weldon
+3  A: 

Updated Answer - my original was misleading and incomplete.

First I should apologize for much of my comments and responses to this question.

After reading the spec, the distinction between bitwise and conditional operators is much less clear cut.

According to section 14.10 of ECMA-334:

The &, ^, and | operators are called the logical operators.

for integer operations:

1 The & operator computes the bitwise logical AND of the two operands, the | operator computes the bitwise logical OR of the two operands, and the ^ operator computes the bitwise logical exclusive OR of the two operands. 2 No overflows are possible from these operations.

According to section 14.11:

The && and || operators are called the conditional logical operators. 2 They are also called the "short-circuiting" logical operators.

14.11.1

1 When the operands of && or || are of type bool, or when the operands are of types that do not define an applicable operator & or operator |, but do define implicit conversions to bool, the operation is processed as follows: 2 The operation x && y is evaluated as x ? y : false. 3 In other words, x is first evaluated and converted to type bool. 4 Then, if x is true, y is evaluated and converted to type bool, and this becomes the result of the operation. 5 Otherwise, the result of the operation is false. 6 The operation x || y is evaluated as x ? true : y. 7 In other words, x is first evaluated and converted to type bool. 8 Then, if x is true, the result of the operation is true. 9 Otherwise, y is evaluated and converted to type bool, and this becomes the result of the operation.

14.11.2

1 When the operands of && or || are of types that declare an applicable user-defined operator & or operator |, both of the following must be true, where T is the type in which the selected operator is declared: 2 The return type and the type of each parameter of the selected operator must be T. 3 In other words, the operator must compute the logical AND or the logical OR of two operands of type T, and must return a result of type T. 4 T must contain declarations of operator true and operator false. Paragraph 2 1 A compile-time error occurs if either of these requirements is not satisfied. 2 Otherwise, the && or || operation is evaluated by combining the user-defined operator true or operator false with the selected user-defined operator: 3 The operation x && y is evaluated as T.false(x) ? x : T.&(x, y), where T.false(x) is an invocation of the operator false declared in T, and T.&(x, y) is an invocation of the selected operator &. 4 In other words, x is first evaluated and operator false is invoked on the result to determine if x is definitely false. 5 Then, if x is definitely false, the result of the operation is the value previously computed for x. 6 Otherwise, y is evaluated, and the selected operator & is invoked on the value previously computed for x and the value computed for y to produce the result of the operation. 7 The operation x || y is evaluated as T.true(x) ? x : T.|(x, y), where T.true(x) is an invocation of the operator true declared in T, and T.|(x, y) is an invocation of the selected operator |. 8 In other words, x is first evaluated and operator true is invoked on the result to determine if x is definitely true. 9 Then, if x is definitely true, the result of the operation is the value previously computed for x. 10 Otherwise, y is evaluated, and the selected operator | is invoked on the value previously computed for x and the value computed for y to produce the result of the operation. Paragraph 3 1 In either of these operations, the expression given by x is only evaluated once, and the expression given by y is either not evaluated or evaluated exactly once. Paragraph 4 1 For an example of a type that implements operator true and operator false, see §18.4.2.

John Weldon
Matthew Flaschen
@Matthew, this question is posed more broadly than as pertains to booleans.
John Weldon
@John, actually I think I disagree. It is clear from the second example that x and y are booleans. Bitwise operators never enter into the question.
Matthew Flaschen
@Matthew; Agreed, it could be interpreted that way.
John Weldon
+6  A: 

It's not logical vs. conditional, it's bitwise vs. logical.

x & y    // bitwise AND, 0100 & 0101 = 0100
x | y    // bitwise OR,  0100 | 0010 = 0110

x && y   // true if both x and y are true
x || y   // true if either x or y are true

Edit

By popular demand, I should also mention that the arguments are evaluated differently. In the logical version, if the result of the entire operation can be determined by the first argument, the second argument is not evaluated. This is called short-circuit evaluation. Bitwise operations have to evaluate both sides in order to compute the final value.

For example:

x.foo() && y.bar()

This will only call y.bar() if x.foo() evaluates to true. Conversely,

x.foo() || y.bar()

will only call y.bar() if x.foo() evaluates to false.

Cogwheel - Matthew Orlando
OK. What about lazy evaluation? Are you going to mention that? Because if you do, I can delete my most unpopular answer.
Robert Harvey
Lazy evaluation is a subset of the logical operations way of operating. Should be mentioned, but is irrelevant to the question.
John Weldon
@John Weldon: The question is about the differences between the operators. And laziness surely is one of them.
0xA3
@0xA3, the concept of 'short-circuiting' is specific to a logical operation. It doesn't really apply to bitwise operations except in certain cases.
John Weldon
@Robert, @0xA3 -- I've retracted most of my opinions and arguments here... see my answer for specifics.
John Weldon
@Robert Harvey: I tossed this answer up as I was leaving work... Just getting back to it now. I've added an edit per your suggestion :)
Cogwheel - Matthew Orlando