Question

Consider the following codes:

int a = 3;
int b = 0;
b = a > 0 ? ++b, ++a : --a, b = 0;

After execution, I get the value of b to become 0 and the value of a to become 4.
That means the result of condition expression, a > 0 is evaluated as true and the expression a++ has been executed, while the expression b = 0 after , hast been executed ,too. In other words, the expression b = 0 is not an operand of the ternary operator, while ++b is. Otherwise, b = 0 won't be executed since the condition expression isn't evaluated as false.

My question is "according to what rule does the compiler kick b = 0 out of the ternary operator's operand?"

The operators in the third statement includes: ++ and --, which have the highest precedence, >, which has the second largest precedence, ? : and =, which have the third largest precedence and , with the lowest precedence. I know that operators with higher precedence should determine their operands earlier so that ++,--, and > are handled first. Then the statement is equivalently:

b = (a > 0) ? (++b), (++a) : (--a), b = 0;

Now, it's = and ?:'s turn to be handled. The associativity of = and ?: is right-to-left, so I consider the compiler will parse the statement from the right end.The first operator met is = and so b = 0 is grouped together. The second met operator is ,. Since it's precedence is lower then the current operators being analyzed, I assume the compiler will just skip it. Then the compiler met :, which is a part of ternary operator, so it keeps parsing.(Actually I don't know how the compiler can know that : is a part of ?: before parsing the whole ternary operator) Problem comes here. The next operator met by the compiler is , but the compiler haven't finished determining the operands of ?: yet. The , has lower priority than ?:. Theoretically it should be skipped; surprisingly, in practical test, the (++b) and (++a) have been concatenated by the , operator at this time and both are considered as the operand of ?:. That makes me confused. Why does the last , is ignored and doesn't included in the operand of ?: while the previous , in statement is kept in the operand of ternary operator?

May someone clarify the concepts of precedence and associativity with this example? I'm really confused about the executing result when first taking a sight of this piece of codes. I had thought that the expression b=0 is also a part of the ternary operator's operand; therefore b = 0 will only be executed if a > 0 is false.

Thanks in advance.

Was it helpful?

Solution

Precedence and associativity are different concepts, but technically the C and C++ standard specifies none. Instead they give the grammar rules to deduce the structure of the expression.

The relevant rules are:

conditional-expression:
    logical-or-expression
    logical-or-expression ? expression : assignment-expression

expression:
    assignment-expression
    expression , assignment-expression

primary-expression:
    ( expression )

postfix-expression:
    primary-expression
    ...

And so on...

The idea is that each type of expression can generate a composite expresion or another type of expression of lower precedence. You can only go up to the root expression by using parenthesis.

With that in mind, note that the conditional-expression that uses the ?: actually has different types of expressions in each of the three subexpressions. The middle one is expression so it will accept any kind of expression, even with , or = (no ambiguity here because of the ending :).

But note that the last one is assignment-expression, that is any kind of expression except the one with ,. If you want to use that, you will have to enclose it with () creating a primary-expression instead.

Bonus explanation: the first expression is logical-or-expression, and if you look carefully to the grammar you'll see that it excludes assignment operators, the conditional operator and the comma operator.

So your expression:

b = a > 0 ? ++b, ++a : --a, b = 0

Is actually a expression comma assignment-expression, where the first expression is b = a > 0 ? ++b, ++a : --a and the second assignment-expression is b = 0.

And so on...

OTHER TIPS

Your expression is evaluated as (b = ((a > 0) ? (++b, ++a) : (--a))), (b = 0);.

As you say the ?: has higher precedence than the comma operator, so the b=0 does not belong to the ternary conditional. The difference for the left and the right part of the ternary operator is, that on the left side the compiler tries to evaluate the complete string ++b, ++a as an expression (knowing that the part between ? and : must be an expression, while on the right side the compiler tries to parse an expression as far as it can. And precedence of operators says the compiler must stop at the ,. On the left side the compiler does not stop on the , because this is a legal part of the expression.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top