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
Createprocess Doesn't Pass Command Line Arguments
How to Read from a Text File, Character by Character in C++
If Temporaries Are Implicitly Non-Modifiable, How Does This Work
Link .So File to .Cpp File via G++ Compiling
Can a Single Member of a Class Template Be Partially Specialized
When Instantiating a Template, Should Members of Its Incomplete Argument Types Be Visible
C++ Visual Studio "Non-Standard Syntax; Use '&' to Create a Pointer to Member"
Why Would Anyone Use Set Instead of Unordered_Set
Why Does This Call the Default Constructor
Reason for Using Non-Type Template Parameter Instead of Regular Parameter
Does Resizing a Vector Invalidate Iterators
How to Download a File with Winhttp in C/C++
Write a Recursive Function That Reverses the Input String
C++ Read/Write Class From/To Binary File
Using Boost::Iostreams::Mapped_File_Source with Std::Multimap