Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Comma operator returns an unchanged value

Tags:

c++

I am following the C++ primer 5th edition book as it was mentioned to be a good beginner friendly book to learn C++. As I proceeded to solve the exercise in chapter 4 I came across the question 4.33 in section 4.10. I am posting below the question as written in book:

Using Table 4.12 (p. 166) explain what the following expression does:

someValue ? ++x, ++y : --x, --y
 

The question was a bit confusing to me so I decided to look it over web and found a git repository containing solution that looks something similar to what I've typed below:

#include<iostream>

int main()
{
    int x = 1, y = 9;
    std::cout << (true ? ++x, ++y : --x, --y) << std::endl;
    std::cout << x << "\t" << y << std::endl;
    std::cout << (false ? ++x, ++y : --x, --y) << std::endl;
    std::cout << x << "\t" << y << std::endl;
    return 0;
}

My query is upon running the above code, why does the compiler shows 9 on it's first cout statement, i.e, on the following statement:

std::cout << (true ? ++x, ++y : --x, --y) << std::endl;

the output is 9. From what I know, comma operator evaluates and discards its left hand values and returns its left hand expression's value as its result, also the preincrement operator increments the operand's value and returns the incremented value. So shouldn't that code output 10, i.e., the ++x increments x to 2 and then the value is discarded and then the ++y increments y to 10 and then returns its value. Also when I use the brackets the output on the same statement changes to 10 and behaves as I expect it to behave, i.e., doing this:

std::cout << (true ? (++x, ++y) : (--x, --y)) << std::endl;

outputs 10. Also in the solution the behaviour is written as:--> Equivalent to: (some_Value ? ++x, ++y :--x), --y If true, return y; else, return --y.

but from what I understand it should be:--> - Equivalent to: (some_Value ? ++x, ++y :--x, --y) If true, return ++y; else, return --y.

ie, the placement of the bracket is what bothered me. I know this is a tiny difference but I don't want to get the concept wrong. Am I missing something here?

like image 319
Jiaar Avatar asked Jan 25 '23 16:01

Jiaar


2 Answers

This expression:

(true ? ++x, ++y : --x, --y)

is misleading with regards to what the false clause of ?: is. Putting parentheses in the right place gives:

( (true ? (++x, ++y) : --x), --y)
  // true ^^^^^^^^^^  
  //            false  ^^^                           

Now, since the condition of ? is true, x and y get incremented to 2 and 10 respectively, in that order. After the ?: is evaluated, y is decremented to 9, which is the result of the entire expression.

like image 80
cigien Avatar answered Jan 27 '23 06:01

cigien


Although you are correct in your assumption that the order of evaluation of expressions separated by the comma operator is guaranteed (to be left-to-right), what you have not considered here is the priority of operators.

The comma operator has the lowest priority of all. So, the following:

    std::cout << (true ? ++x, ++y : --x, --y) << std::endl;

Is the equivalent of this (adding parentheses to show how the compiler sees things):

    std::cout << ( (true ? (++x, ++y) : --x), --y ) << std::endl;

Note that the parentheses around the first use of the comma operator are there because the compiler is already processing the ternary ? and evaluates the entire expression preceding the :, in 'one fell swoop'.

Thus after incrementing x and y, the code then decrements y - giving your output as the 'original' value.

like image 24
Adrian Mole Avatar answered Jan 27 '23 06:01

Adrian Mole