Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why doesn't GCC's ternary extension support assignment?

GCC has an awesome ternary expression extension to C which allows us to create a statement like this:

int x = some_var ?: 10; // expands to some_var ? some_var : 10

Which is really nice, and while it's not particularly intuitive, it does work. Most binary operators in the C language have an additional operator associated with them, which allows for assignment:

x = x + 2;

// instead, we can say
x += 2;

Since this is the case, and the norm for most binary C operators (+, -, *, /, %, |, &, ^), why isn't this the case for the ternary extension operator:

int x = ...;
x ?:= 2; // error: Expected expression before '=' token

// which would expand to
x = x ?: 2;

The only operators which don't support this in standard C are the logical operators (||, &&), which the definitely ternary doesn't fall under, so why can't we do this?

I would really like to make a smiley face with a cool hair-do in my code, but I can't! Was this an oversight in designing the operator, or intentional and documented somewhere? Is it a result of the operator short-circuiting its operand, or something else entirely?

like image 537
Richard J. Ross III Avatar asked Jun 04 '13 18:06

Richard J. Ross III


1 Answers

To answer the question, I believe there are some other questions that needs to be answered as well.

Why is there a ?: operator in the C language and why is it better than if-else?

As far as I know, nobody has been able to answer that question, without merely stating their own subjective opinions. K&R 2.11 states that

"The conditional expression often leads to succinct code."

and then they illustrate this with the line

printf("%6d%c", a[i], (i%10==9 || i==n-1) ? '\n' : ' ');

which is their own subjective, muddy opinion. Personally, I believe that

printf("%6d", a[i]);

if(i%10==9 || i==n-1)
  printf("\n");
else
  printf(" ");

is far, far clearer since I can read and understand that code in 10 seconds, as opposed to 1 minute to read and understand the K&R version. Also, my code separates the integer printing from the unrelated formatting. But of course, that is my subjective opinion, there is no obvious right or wrong.

As for official sources, the C99 rationale version 5.10, 6.5.15 doesn't really mention why the ?: operator is needed either. It mainly just states that the behavior of the operator has been altered in the new standard:

The syntactic restrictions on the middle operand of the conditional operator have been relaxed to include more than just logical-OR-expression: several extant implementations have adopted this practice.

The type of a conditional operator expression can be void, a structure, or a union; most other operators do not deal with such types. The rules for balancing type between pointer and integer have, however, been tightened, since now only the constant 0 can portably be coerced to a pointer.

So if someone has an urge to perform arithmetic on struct or union types, the ?: is supposedly more handy than if-else. I see no obvious benefit from this, but at least it is some reason for the operator to exist.

The next question would then be:

Why is there a compiler extension to the ?: operand in the GCC compiler?

The answer to this is mentioned here:

When it becomes useful is when the first operand does, or may (if it is a macro argument), contain a side effect. Then repeating the operand in the middle would perform the side effect twice. Omitting the middle operand uses the value already computed without the undesirable effects of recomputing it.

So this GCC extension has nothing to do with readability or language consistency, it was merely added to avoid unwanted side effects.

Then to attempt to answer the original question:

Why doesn't GCC's ternary extension support assignment?

Probably because accessing the lvalue in an assignment condition doesn't typically yield any unwanted side effects. x = x ? : 2; would only have unwanted side effects if x was declared as a volatile - reading a volatile variable is a side effect. So the only practical use I can see with x ?:= 2; would be to prevent someone from accessing the same volatile variable twice in the same conditional expression.

And that is a feature of very narrow and limited value. It would perhaps be useful in some special embedded system case where you read hardware registers in a demanding real-time system... apart from that, I see no uses for it.

Nor can I find any official or canonical sources stating any use for the ?: operator itself, apart from tradition and subjective coding style preferences.

like image 67
Lundin Avatar answered Sep 30 '22 14:09

Lundin