Ternary Conditional and Assignment Operator Precedence

Ternary conditional and assignment operator precedence

The operator precedence in the C/C++ language in not defined by a table or numbers, but by a grammar. Here is the grammar for conditional operator from C++0x draft chapter 5.16 Conditional operator [expr.cond]:


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

The precedence table like this one is therefore correct when you use assignment on the left side of the doublecolon, but not when used on the right side. What is the reason for this asymmetry I have no idea. It may be a historical reason: in C the conditional result was not lvalue, therefore assigning something to it had no sense, and allowing assignment to be accepted without parentheses might seem smart at that time.

Does the C/C++ ternary operator actually have the same precedence as assignment operators?

The answer for C++ is that ?: and = have the same precedence. Yes, almost every C++ operator precedence table out there is wrong.

In C it doesn't matter whether ?: is higher than = or not, because in C the ?: operator is not allowed to evaluate to an l-value, which is what it would have to do if precedence were to influence the behavior (given that they are already RTL associative). See the discussion under Luchian Crigore's answer for example.

Perhaps this error is so widespread because early C++ operator precedence tables may have been copied and extended from C tables. And perhaps the error has persisted because the only counterexample - expressions of the form a?b:c=d - are rarely used. Perhaps.

Ternary operator precedence and assignment

Yes, they are equivalent. = comes last.

Operator precedence with JavaScript's ternary operator

Use:

h.className = h.className + (h.className ? ' error' : 'error')

You want the operator to work for h.className. Better be specific about it.

Of course, no harm should come from h.className += ' error', but that's another matter.

Also, note that + has precedence over the ternary operator: JavaScript Operator Precedence

Can someone explain why the conditional operator and the assignment operator behave strangely when used together?

If you look at the actual grammar, the two "branches" of the conditional operator are assignment expressions. Thus,

false ? null : x = 1;

is parsed as

false ? (null) : (x = 1);

Because the first expression in a ? : construct is a short-circuit expression in the grammar, the expression

x = 1 ? alert(x) : null;

is parsed as

x = (1 ? alert(x) : null);

Assignment in ternary operator

It has to do with the formal definition of the conditional operator. From section 6.5.15 of the C standard:

conditional-expression:
logical-OR-expression
logical-OR-expression ? expression : conditional-expression

The second clause of a conditional can be any expression, while the third clause can only be a conditional expression (of which as assignment is not). Put another way, the conditional operator ?: has higher precedence than the assignment operator =.

So this:

a > b ? a=4 : ' '

Is the same as this:

(a > b) ? (a=4) : (' ')

But this:

a > b ? ' ' : b=4;

Is the same same as this:

((a > b) ? (' ') : b)=4;

And the result of the conditional operator cannot be assigned to (i.e. it is not an lvalue) so you get an error.

If you add parenthesis you can get something that compiles:

a > b ? ' ' : (b=4);

Granted, these statements don't look like the best use case for a conditional and should probably be rewritten as:

if (a>b) a=4;

And:

if (a<=b) b=4;

ternary operator and assignment operator

Your linked question's (Does the C/C++ ternary operator actually have the same precedence as assignment operators?) answer by @hvd shows the answer.

The C++ and C grammars for ?: are different.

In C++, the rightmost operand is allowed to be an assignment expression (so the compiler [greedily] treats the = are part of the ?:) while in C the rightmost operand is a conditional-expression instead. Thus in C as soon as the compiler hits the = the analysis of ?: is complete and it treats it as k = ( 21 > 3 ? 12 : j ) = 10.

Oddity with using || for assignment where Conditional (ternary) operator is second option

|| is lazy - it will not attempt to evaluate the right-hand side of a || of the left-hand side is determined to be truthy. If you had done b || 1 instead of 1 || b, it would have tried to evaluate b first, and an error would be thrown:

const a = b || 1 ? 3 : 4

What is wrong with this assignment in a conditional operator?

a[i]>90 ? a[i]=a[i]-32 : a[i]=a[i]+32;

is not evaluated as

a[i]>90 ? (a[i]=a[i]-32) : (a[i]=a[i]+32);

since = has lower precedence than ?:. In standard C you can't write it as above although some compilers allow it as an extension.

You could write it as the more readable (and portable)

a[i] += a[i] > 90 ? -32 : +32;


Related Topics



Leave a reply



Submit