1
  1. cout << string_1 << string_2 << string_3;

The line above is processed from left to right, first the operator "<<" operates on "cout" and "string_1", which returns an ostream object which is later used to operate on "string_2", and so on to "string_3".

  1. a = b = 5;

In the line above, the code is processed from right to left. First the operator "=" operates on "b" and "5", which returns an int object to operate with "a" on the next "=" operator.

I might be wrong on how these lines are processed.

Please help me understand why the compiler is changing the order of operations in both cases.

Zoe
  • 27,060
  • 21
  • 118
  • 148
ashwath s
  • 51
  • 4
  • 4
    Because that's how the operator associativity is defined: https://en.cppreference.com/w/cpp/language/operator_precedence – UnholySheep Dec 27 '21 at 16:23
  • 4
    Because this is how C++ works: some binary operators in C++ are left-associative, other are right-associatie. See your C++ textbook for more information. Learning C++ also includes learning all the operator and associativity rules (in general). – Sam Varshavchik Dec 27 '21 at 16:23
  • The direction is determined by the chosen operator. Your observations are correct, and the reason is because `<<` is always processed left-to-right and `=` is always processed right-to-left. – Drew Dormann Dec 27 '21 at 16:27
  • 1
    I see this question is getting hit with downvotes. In my opinion it is clear and focused, if perhaps not researched. I'm not sure if there is a good duplicate of this question. Perhaps https://stackoverflow.com/questions/930486/what-is-associativity-of-operators-and-why-is-it-important – Drew Dormann Dec 27 '21 at 16:33
  • 1
    Tip: just learn the general rule that **binary operators are left-to-right**, with the *exception to the rule* that **but for assignment, which is right-to-left**. But you still also have to be familiar with the *precedence* rules too. For funsies. – Eljay Dec 27 '21 at 16:37

3 Answers3

1

As @UnholySheep posted in a comment:

Because that's how the operator associativity is defined: https://en.cppreference.com/w/cpp/language/operator_precedence

Tomerikoo
  • 18,379
  • 16
  • 47
  • 61
anatolyg
  • 26,506
  • 9
  • 60
  • 134
1

This is a wise design decision.

Because you intuitively expect

cout<< string_1 << string_2 << string_3;

to emit the three strings in that order, and you expect

a = b = 5;

to assign 5 to both a and b (rather than performing a= b; b= 5;)

  • The `<<` operator was designed to be bit-shifting, so its operator associativity, precedence, and so on are all optimized for bit-shifting. It's overloaded for stream insertion, but overloading doesn't change the language grammar, so you may find intuition violated. (All that said, the iostream designers would not have chosen `<<` for stream insertion if it weren't already left-associative. But don't mix up cause and effect.) – Ben Voigt Dec 27 '21 at 17:06
  • Also, your expectation of what `a = b = 5;` does is based on your knowledge of the language, not intuition. Someone implementing digital IIR filters (where delay chains are commonplace) might find it quite surprising that said code doesn't implement a delay chain. Furthermore, it doesn't "assign `5` to both `a` and `b`", it assigns `5` to `b` and then the contents of `b` to `a`, which depending on datatype, volatility, etc might not actually be `5`. – Ben Voigt Dec 27 '21 at 17:13
  • @BenVoigt: technically, it assigns the left value of the expression `b= 5` to `a`. And I do mean that `a= b= 5` was designed to match peoples intuition independently of any knowledge of the language. Otherwise, the reasoning would be perfectly circular. –  Dec 27 '21 at 17:18
1

The fundamental reason behind this difference in processing order is operator precedence1.

Precedence and associativity determine how the operands are grouped in an expression.

So there are 2 important points to keep in mind here:

  1. Operands of operators with higher precedence group more tightly than operands of operators at lower precedence.
  2. Associativity determines how to group operands with the same precedence.

Lets consider some examples to clear this up.

Example 1

Consider the expression 3+4*5+2.

Now the value(result) of this expression depends upon how the subexpressions are grouped.

In this example, multiplication and division have the same precedence as each other but they have higher precedence than addition. Thus, using Point 1 above, operands to muliplication and division group before operands to addition.

Also, the arithmetic operators are left associative which means operands of operators at the same precedence group left to right. This is what associativity meant in point 2 above.

Now, using these two facts the expression 3+4*5+2 is equivalent to:

((3+(4*5))+2)

which will result in a value of 25.

Example 2

Consider the expression cin >> x >> y;

In this example, the IO operators are left associative which means they group left to right. This is why we are able to combine IO operations in a single expression as above. This also means that the above expression is equivalent to writing:

((std::cin >> x) >> y);

Example 3

Lets come back to your example expression cout << string_1 << string_2 << string_3

As i said in example 2, IO operators are left associative which means they group left to right. Again, this means the above expression is equivalent to writing:

(((cout << string_1) << string_2) << string_3)

Example 4

Consider the expression a = b = 5

In this case, the assignment operator is right associative which means they group right to left. Thus the above expression is equivalent to writing:

(a = (b = 5))

This means 2 things:

  1. the rightmost assignment b = 5 is the operand of the leftmost assignment operator.
  2. because assignment returns its left-hand operand, the result of the rightmost assignment(which will be b in this case) is assigned to a.

1 Precedence specifies how the operands are grouped. It says nothing about the order in which the operands are evaluated. There is no concept of left-to-right or right-to-left evaluation in C++.

Jason
  • 36,170
  • 5
  • 26
  • 60