Conditional operator differences between C and C++

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?


Solution 1:

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));

Solution 2:

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;