0

In C++, the equality operator's associativity is left to right, as stated here and here and the returned value of an assignment operation is the value assigned to the given variable. (As shown here, here, here, and here, (section 6.5.16, pages 101-104 for the last link).)

According to this information, this:

double d = 5;

if (d == (d = 6))
    cout << "but d was 5...!!!" << endl;
else
    cout << "5!=6 :)" << endl;

should print "5!=6 :)" since the expression, (d == (d = 6)) is equivalent to (5 == (6)) (which is false), but instead, "but d was 5..." is printed. Can anyone explain why?

autistic
  • 1
  • 3
  • 35
  • 80
Kröw
  • 504
  • 2
  • 13
  • 31
  • 1
    Operator associativity doesn't tell you in what order the operands are evaluated. It tells you how they're grouped/parsed. – Cornstalks Jun 12 '17 at 03:47
  • 4
    @Galik: That's false. They **do not** force any order of evaluation. – Cornstalks Jun 12 '17 at 03:47
  • 1
    You might want to read up on [What is associativity of operators and why is it important?](https://stackoverflow.com/questions/930486/what-is-associativity-of-operators-and-why-is-it-important) I also suggest reading [my answer about operator precedence](https://stackoverflow.com/a/20756163/1287251) where I explain how the precedence/associativity affects the compiler's parsing of the code, but not the order of evaluation of arguments. – Cornstalks Jun 12 '17 at 03:48
  • 2
    This is undefined behaviour (the assignment is unsequenced with respect to the left-hand operand of `==`) – M.M Jun 12 '17 at 03:55
  • Please decide on a language. C and C++ are different languages. – Ajay Brahmakshatriya Jun 12 '17 at 04:23
  • Don't tag multiple languages, please. That's spam. If your code compiles using a C compiler and you want to ask about C, use the C tag. Otherwise, if you need a C++ compiler to compile your code or you want to ask about C++, use the C++ tag. – autistic Jun 12 '17 at 04:26

2 Answers2

6

The relevant part of the standard is this:

[intro.execution]/15 Except where noted, evaluations of operands of individual operators and of subexpressions of individual expressions are unsequenced. The value computations of the operands of an operator are sequenced before the value computation of the result of the operator. If a side effect on a scalar object is unsequenced relative to either another side effect on the same scalar object or a value computation using the value of the same scalar object, and they are not potentially concurrent (1.10), the behavior is undefined.

Emphasis mine. Your program exhibits undefined behavior because there's a modification of d (in the right-hand side of the comparison) unsequenced with the value computation of d (in the left-hand side of the same). Associativity and precedence don't enter into this.

Igor Tandetnik
  • 50,461
  • 4
  • 56
  • 85
  • Also, operands of `==` are unsequenced (people coming from other languages tend to assume that there is something like left-right sequencing for operators and function calls) – M.M Jun 12 '17 at 03:58
  • @M.M Isn't it right there in the first sentence? *"evaluations of operands of individual operators and of subexpressions of individual expressions are unsequenced."* Seems pretty clear to me. – Igor Tandetnik Jun 12 '17 at 03:59
  • 1
    Fair enough, I guess I am saying that `==` does not have an "except where noted" exception! – M.M Jun 12 '17 at 04:00
4

You are confusing associativity with order of evaluation.

Left-to-right associativity means

a == b == c 

is interpreted as

(a == b) == c 

That has no relationship with order of evaluation of terms in an expression like a == b. The compiler is free to evaluate a and b in any order. Because of that, in your case, the compiler is free to evaluate d first or (d = 6) first. As a consequence, your program can evaluate to true or false depending which side of the operator gets evaluated first. If there is a race condition (a compiler is free to evaluate them in parallel also), the result will be different from one run to the next.

R Sahu
  • 204,454
  • 14
  • 159
  • 270
  • 1
    Just for clarification is the behavior undefined, or merely unspecified? – Mark B Jun 12 '17 at 03:54
  • I see what you mean now. Is there any way to force the order of evaluation to my liking? – Kröw Jun 12 '17 at 03:56
  • 1
    @MarkB, the quote in [the answer by Igor](https://stackoverflow.com/a/44491199/434551) indicates that it is undefined behavior. – R Sahu Jun 12 '17 at 03:58
  • @Kröw, there may be ways of doing that but I am not sure what your end goal is in this particular case. – R Sahu Jun 12 '17 at 04:00
  • I think the intent was `if (d != 6) { cout << "d was 5\n"; d = 6; } else { cout << "d was 6\n"; }`. In this case you could use `if ( d++ != 6 )` but only because 5 and 6 differ by 1. Note - equality comparison for floating point may be unreliable. – M.M Jun 12 '17 at 04:01
  • @RSahu I have a while loop which sets a variable equal to a value and continues running **only** if the value is not already equal to the variable. – Kröw Jun 12 '17 at 04:02
  • @Kröw, is there is a driving need to combine the "set the value of the variable" and "compare the value of the variable with another value" into one statement? It will be simpler to separate them, IMO. – R Sahu Jun 12 '17 at 04:04
  • @RSahu Mostly efficiency. One statement lowers the amount of processing by a large amount. However, it really isn't necessary at all; I made my code work after separating it, but if there is a way to do this in one statement, I'd like to know how, in case I need it later on. – Kröw Jun 12 '17 at 04:08
  • @Kröw, I would be very surprised if that change will be a factor in performance of your program. If it does, a better place to ask questions related to improving performance will be http://codereview.stackexchange.com/. – R Sahu Jun 12 '17 at 04:39
  • @RSahu Ok, but apart from that, do you know of a way to accomplish the above? – Kröw Jun 12 '17 at 04:52
  • 1
    @Kröw, I still can't visualize the logic you are trying to implement. It might be better to post that in another question, with more details. – R Sahu Jun 12 '17 at 05:53