The problem with writing such an expression is that you can't write to the same variable twice inside it, or the code will invoke undefined behavior, meaning there will be a bug and anything can happen. If a variable is modified inside an expression, that same variable is not allowed to be accessed again within the same expression, unless accesses are separated by so-called sequence points. (C11 6.5/2) See this for details.
So we can't write code such as this:
// BAD CODE, undefined behavior
_Bool first=false;
x = (first?(first=true,exp1):0) + (first?(first=true,exp2):0);
This code invoked undefined behavior because the access to first
between difference places of the expression are unsequenced.
However, it is possible to achieve similar code by using functions. Whenever calling a function, there is a sequence point after the evaluation of the arguments, before the function is called. And there is another sequence point before the function returns. So code such as this is possible:
n = expr(1) + expr(2)
This merely has unspecified behavior - since the evaluations of the operands to + is unspecified. But there is no unsequenced access anywhere, meaning the code can't crash etc. We simply can't know or assume what result it will give. Example:
#include <stdio.h>
static int first=0;
int expr (int n)
{
if(first == 0)
{
first = n;
return first;
}
return 0;
}
int main (void)
{
int n;
printf("%d\n", n = expr(1) + expr(2)); // unspecified order of evaluation
first=0;
printf("%d\n", n = expr(1) + expr(2)); // unspecified order of evaluation
return 0;
}
This gave the output 1 1
on my system, but it might as well have given the output 1 2
, 2 1
or 2 2
. And the next time I execute the program, it may give a different result - we can't assume anything, except that the program will behave deterministically in an undocumented way.
The main reason why this is left unspecified, it to allow different compilers to optimize their expression parsing trees differently depending on the situation. This in turn enables fastest possible execution time and/or compile time.