I read somewhere that the ?:
operator in C is slightly different in C++, that there's some source code that works differently in both languages. Unfortunately, I can't find the text anywhere. Does anyone know what this difference is?
The conditional operator in C++ can return an lvalue, whereas C does not allow for similar functionality. Hence, the following is legal in C++:
(true ? a : b) = 1;
To replicate this in C, you would have to resort to if/else, or deal with references directly:
*(true ? &a : &b) = 1;
Also in C++, ?:
and =
operators have equal precedence and group right-to-left, such that:
(true ? a = 1 : b = 2);
is valid C++ code, but will throw an error in C without parentheses around the last expression:
(true ? a = 1 : (b = 2));
(condition ? a = 1 : b = 2);
-- is this used as a "shortcut" for if-else situations? Would you think that's done often? I tend to consider it misuse :-/ –
Arrington =
in the last part of the ?:
operator is not defined in the C grammar, but many compilers parse it as "a ? b = 1 : c = 1" == "(a ? (b = 1) : c) = 1"
, which will then fail since ?:
is never an lvalue in C. See en.cppreference.com/w/c/language/operator_precedence –
Bowlds The principal practical difference is that in C, evaluation of ?: can never result in a l-value where as in C++ it can.
There are other differences in its definition which have few practical consequences. In C++ the first operand is converted to a bool, in C it is compared against 0. This is analagous to the difference in definition of ==, !=, etc. between C and C++.
There are also more complex rules in C++ for deducing the type of a ?: expression based on the types of the 2nd and 3rd operands. This reflects the possibility of user-defined implicit conversions in C++.
Example code. Valid C++; invalid C.
extern int h(int p, int q);
int g(int x)
{
int a = 3, b = 5;
(x ? a : b) = 7;
return h( a, b );
}
gcc
generates the error: "error: invalid lvalue in assignment" when compiling as C, but the code compiles without error when compiling as C++.
Edit: Although ?: can't return an l-value in C, perhaps surprisingly the grammar for ?: is:
conditional-expression:
logical-OR-expression
logical-OR-expression ? expression : conditional-expression
This means that a ? b : c = d
parses as (a ? b : c) = d
even though (due to the 'not an l-value' rule) this can't result in a valid expression.
C++ changes the grammar to this:
conditional-expression:
logical-or-expression
logical-or-expression ? expression : assignment-expression
While the extension to allow conditional-expression to be an l-value in some situations would have made a ? b : c = d
valid without the grammar change, the new grammar change means that the expression is now valid but with the different meaning of a ? b : (c = d)
.
Although I don't have any evidence for it, my supposition that as the grammar change couldn't break compatibility with existing C code, it was more likely that the new grammar would produce fewer surprises with expressions such as:
make_zero ? z = 0 : z = 1;
=
operator cannot contain a non-parenthesized ?:
operator. The suggested (a ? b : c) = d
parse is not really possible. In C grammar a ? b : c = d
expression is not parsable at all. Any compiler that interprets it as (a ? b : c) = d
is doing it at its own risk. (This is typically the case in hybrid C/C++ compilers that attempt to unify C and C++ grammars under the hood.) Formally, there's no problem in it, since invalid code is still rejected. But "not an lvalue" message is misleading. –
Ignatia a ? b : c = d
is simply syntactic gibberish, a non-parsable sequence of tokens. It is not an expression. Claiming that it assigns to a non-lvalue is incorrect, since there's no "assignement" here. –
Ignatia © 2022 - 2024 — McMap. All rights reserved.