Why doesn't GCC's ternary extension support assignment?
Asked Answered
P

1

6

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?

Puff answered 4/6, 2013 at 18:57 Comment(9)
Not sure what x ?:= 2; would mean, but maybe x ?= ValueWhenXTrue:ValueWhenXFalse;.Espadrille
I fail to see how this question is 'not constructive'. It is completely on-topic, discussing the behavior of a specific operator in GNU C. It is properly tagged, giving simple, concrete examples, and has a definitive answer.Puff
@chux In human speak, it would mean if x is zero, set it to 2.Puff
What would the semantics of x ?:= 2 be? In the expression: a = x ? b : c, there are four operands, in the extension a = x ?: b there are three, in your proposal a ?:= b there are only two - the value being assigned and the value to be assigned, but no conditional - you have rendered it meaningless - there is no reasonable semantic interpretation.Lava
@Lava the condition would be the lvalue you are assigning to.Puff
I'm fairly certain that this will only lead to answers containing various people's personal opinions, without any sources stated, so it is not constructive. Furthermore, the question contains a lot of your personal, subjective opinions about various obscure operators, stated as if they are absolute truths. I really don't see how int x = some_var ?: 10; is awesome, or would solve any programming problem, or make the code less confusing.Vasya
@Vasya the answers given do not cause the question itself to be bad. Yes, I used a bit of hyperbole, but this is a community edited site - feel free to modify my question if you feel something is incorrect.Puff
Well ... I see no point for the operator ?:= not existing. Let's join WG14 and suggest a change to the Standard (maybe it gets into the next Standard).Ynez
@RichardJ.RossIII: Then you should edit the question to make the semantics clear rather than explaining in a comment. You cannot propose a modification or extension to the standard without making the proposal at least as unambiguous as the standard itself. This discussion has already sucked more of our lives than such a feature will ever save us!Lava
V
8

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.

Vasya answered 4/6, 2013 at 20:12 Comment(1)
Unusually perhaps, we are in agreement ;-) K&R managed to shoot themselves in the foot by using an example that is probably less clear than the alternative. ?: can indeed make code more succinct and clearer - their example however is not one of them! The operator allows the use of an expression where control flow would otherwise be needed - and that is sometimes useful.Lava

© 2022 - 2024 — McMap. All rights reserved.