views:

385

answers:

14

Which order is the and && operator evaluated

For example the following code

if (int alpha = value1-value2 && alpha > 0.001)
    //do something

threw an exception that alpha is being used without being initiated. I thought the expression left of the && would always initiate the value of alpha first, but it seems I may be wrong

Any idea?

Thanks

+5  A: 

The left side is always evaluated first. The problem here is operator precedence. See if this doesn't work better:

if ((int alpha = value1-value2) && (alpha > 0.001))
Jerry Coffin
If I am not mistaken, the declaration of `alpha` like that is not permitted in the body of the `if` when it is part of a larger expression.
James McNellis
@James:offhand, I don't remember, but you could be right. Under the circumstances, I'd probably use: `int alpha = value1-value2; if (alpha>0.001)` As written, the code also includes a redundant comparison to zero.
Jerry Coffin
Per this answer here, it is not allowed: http://stackoverflow.com/questions/1516919/1516966#1516966 (took me a while to find it). MSVC++ 2008 and Intel C++ 11.1 both reject it, too.
James McNellis
+11  A: 

This gets parsed as:

if (int alpha = (value1-value2 && (alpha > 0.001)))

... because && has a higher "parsing precedence" than = -- which is probably not what you want. Try:

int alpha = value1-value2; 
if (alpha && (alpha > 0.001))
Kornel Kisielewicz
You can't have a declaration in a subexpression. Your "try" version is invalid.
AndreyT
AndreyT
@AndreyT: Fixed, sorta. The term "precedence" was used in terms of lexer token precedence, not operator.
Kornel Kisielewicz
`if ( alpha > 0.001 )` does the same thing
Potatoswatter
+1  A: 

If I'm not mistaken, that operation is undefined. Asigning to to variable and then referring to that same variable in a single statement is undefined.

slebetman
Alok
Jerry Coffin
@Alok, What do you expect the "well-defined" value of alpha to be? Sequence point or not, it's still being used uninitialized.
Dan Olson
Alok
I agree, but that's not what the question is about.
Dan Olson
"Asigning to to variable and then referring to that same variable in a single statement" is perfectly well defined. Otherwise we'd have `a = a + 1` as undefined. The only important thing to watch for here is that the variable should be read for the purpose of determining its new value.
AndreyT
+1  A: 

I generally always use parenthesis just to make my code a little more clear of my intent.

cquillen
A: 

The problem is that the statement is evaluating like this:

if (int alpha = (value1-value2 && alpha > 0.001))

Use parentheses to fix the left- and right-hand sides of the && operator:

if ((int alpha = value1-value2) && (alpha > 0.001))

Aaron
+2  A: 

After clarifying how it works (for educative purposes), do not do this. Do not mix variable initialization/assignment and comparisons in the same statement.

It is better if each statement is either a "command" or a "query" alone.

And it is much, much better if a condition inside an "if" is very clearly readable, and unequivocally bool. Not integer, no nothing, just bool.

The first part of your condition is an integer. Then you do an and with a bool. You are forcing a conversion with no need at all. Give if's and conditional operators exactly what they ask for: bools.

Daniel Daranas
A: 

My guess is that it's because you're declaring the storage inside the "if" statement. I didn't even think that would compile.

Try this.

int alpha;
if ((alpha=value1-value2) && alpha>0.001)

But I don't think this is doing what you need. You have alpha as an int, and you're then comparing it to a floating point value. The first part of the && statement will retrun true as long as alpha is not zero and the second part will return true if alpha is greater than 0. So you should probably do this

int alpha;
if ((alpha=value1-value2)>0)

or for much more readable code

int alpha=value1-value2
if (alpha>0)

But to answer your original question: && is executed left to right and short circuited when the answer is obvious. I.e., if the first part of the && is false, the second isn't even evaulated!

miked
+1  A: 

It's evaluated from left to right.

In your case, however the assignment is the last thing to happen and they whole thing would behave as (where alpha is used as part of the calculation to get the result to initialize it):

if (int alpha = (value1-value2 && alpha > 0.001))

You can't mix variable declarations into complex expressions, therefore the following won't compile:

if ((int alpha = value1-value2) && (alpha > 0.001))

Therefore you'll need to split it up to two lines:

int alpha = value1 - value2;
if (alpha > 0.001)
UncleBens
A: 

Here's an article listing operator precedence and associativity.

From what I can tell, your intent is to declare a temporary, assign it the value of value1-value2, then test the result and enter the if block if it is greater than some value. alpha is being declares as an int, but you seem to be comparing it against a double. alpha should be a double.

Your'e being creative with the use of temporaries. Clear is often better than cute. Do this instead:

double alpha = value1-value2;
if (alpha > 0.001)
John Dibling
A: 

According to : http://en.wikipedia.org/wiki/Operators_in_C_and_C%2B%2B

- LtR
> LtR
&& LtR
= RtL

given your example

(int alpha = value1-value2 && alpha > 0.001)
(int alpha = (value1-value2) && alpha > 0.001)
(int alpha = (value1-value2) && (alpha > 0.001))
(int alpha = (value1-value2) && (alpha > 0.001))
(int alpha = ((value1-value2) && (alpha > 0.001)))
XAder
The `=` in this case is not an operator. So, using the precedence table for `=` is a completely meaningless thing to do.
AndreyT
+2  A: 

Answering the question in the title, it depends on the types of the operands.

For builtin-types, && short-circuits, meaning that the LHS is evaluated, and if it is false then the RHS is not evaluated at all.

For user-defined types which have overloaded operator&&, it does not short-circuit. Both sides are evaluated, in unspecified order, and then the function is called.

I think others have handled the question you need answered, though.

Steve Jessop
David Thornley
AndreyT
David Thornley
AndreyT
Steve Jessop
Or another example: you're writing a class representing expressions in propositional calculus. They don't convert to `bool`, but there are obvious and productive meanings of `operator` reads a little better than `Proposition C = and(A,B);`, or `A.and(B);`.
Steve Jessop
+1  A: 
if (int alpha = value1-value2 && alpha > 0.001)

According to the rules would be evaluated in order as

1.  (value1-value2)   [evaluate subtraction]
2.  && (left side)    [test left side]
3.  (alpha > 0.001)   [evaluated only if value-value2 != 0]
4.  && (right side)   [test right side]
4.  alpha =           [assignment]

In step 3, alpha is first evaluated. Since it hasn't been assigned—and maybe not declared, the rules aren't clear on this—it produces an error.

The flaw is that assignment is lower precedence than &&. What still doesn't work, but is closer:

if (int alpha = value1-value2, alpha > 0.001)

Gcc gives error: expected expression before ‘int’. Well maybe it's not closer. With the original statement, gcc says the same thing.

wallyk
A: 

As written this expression does the following:

  1. Evaluates value1 - value2 and converts it to a bool by implicit comparison against zero - i.e., it is effectively (value1 - value2) != 0
  2. Evaluates alpha > 0.001 after truncating 0.001 to int(0). At this point alpha is not initialized.
  3. Calculates the Logical AND of the previous two evaluations
  4. Converts the Boolean result of the Logical AND back to an integer

I think that this summarizes the rest of the posts. The only reason that I posted a separate answer is that I could not find one that mentioned both when alpha was not initialized and all of the conversions that are occurring here; wallyk's answer is closest.

Of course, the rest of the answers that suggest that you use parentheses and a separate declaration of alpha are exactly what you should do to fix this. Declaring variables within an if statement is part of the language that I haven't found a good use for - declarations within repetition structures seems more appropriate.

D.Shawley
+9  A: 

The bottom line here is that what you are trying to express cannot be possibly expressed by a single logical condition with the declaration of alpha being embedded into it (despite what some other answers claim).

The other answers already explained to you that your condition is not parsed the way you think it is parsed, although many answers make an obvious error of referring to the precedence of = operator in the condition, while in reality there's no = operator there whatsoever. The correct explanation is that when you declare a variable in the if condition, the syntax is that of declaration with an initializer, so the whole thing is parsed the same way as

int alpha = value1 - value2 && alpha > 0.001;

would be parsed, i.e. it is a declaration of int alpha initialized with value1 - value2 && alpha > 0.001. There's no operator = in it. And I hope now you can see why the compiler says that you are reading an uninitialized variable in the initializer expression. The compiler would make the same complaint on the following declaration

int alpha = alpha; // reading uninitialized variable

for the very same reason.

To achieve what you are literally trying to express, you have to either pre-declare alpha

int alpha;
if ((alpha = value1 - value2) && alpha > 0.001) {
  // whatever 
}

or split your if into two

if (int alpha = value1 - value2) 
  if (alpha > 0.001) {
    // whatever 
  }

However, since the second condition already requires alpha to be greater than 0, it doesn't make much sense to even verify the first one, so the most meaningful thing to do would be to just reduce the whole thing to

int alpha = value1 - value2;
if (alpha > 0.001) {
  // whatever 
}

Of course, as others already noted, the comparison of an int value to 0.001 is a valid, but rather weird thing to do. Just do

int alpha = value1 - value2;
if (alpha > 0) {
  // whatever 
}
AndreyT