C ternary operator, can I omit one part?

Viewed 238

I wanted to know if there's a way to omit second or third part of the ternary operator? I already read this and similar ones but they didn't help.

What I specifically want is something like:

x == y ? x*=2;

however this gives me error as gcc expects another expression also. So are:

x == y ? x *=2 : continue;

x == y ?: x /=2;

What can I do in these situations except:

if(x == y) do_something;

Edit for further clarification: As my question seems to be confusing and got all kinds of comments/answers my point was when thinking logically, an else is required after if , so is the default statement in a switch however, neither are mandatory. I was asking if it's the case with ?: also and if so, how.

6 Answers

I wanted to know if there's a way to omit second or third part of the ternary operator?

No, not in standard C.

You can substitute expressions or statements that do not use the conditional operator at all, but in standard C, the conditional operator requires three operands, just like the division operator (/) requires two. You cannot omit any.

Nor is it clear why you want to do. The primary thing that distinguishes the conditional operator from an if [/ else] statement is that expressions using the conditional operator are evaluated to produce values. If you're not interested in that value then using a conditional expression instead of a conditional statement is poor style. A standard if statement is much clearer, and clarity is king. This is a consideration even when you do want the value.

What can I do in these situations except:

if(x == y) do_something;

You can go have a coffee and hope the mood passes.

But if it doesn't, then the logical operators && and || have short-circuiting behavior that might suit, as @EricPostpischil already observed:

  • a && b is an expression analogous to if (a) b;. It evaluates a, after which there is a sequence point. If a was truthy then it evaluates b and that is the result of the expression; otherwise it does not evaluate b and the value of a is the value of the expression. That is the C version of the hypothetical a ? b : (nothing), and why C does not need the latter.

  • Similarly, a || b is an expression analogous to if (!a) b;. b is evaluated and yields the result of the expression if and only if a is falsey. That is the C version of the hypothetical a ? (nothing) : b.

But here again, it is poor C style to use && and || expressions exclusively for their side effects. If you don't care about the result of the operation, then use an if statement.

Or perhaps poor style is the point? If you're shooting for an entry in the International Obfuscated C Code Contest then abusing operators is par for the course. In that case, you could consider rewriting your expressions to use the ternary operator after all. For example,

x == y ? x *=2 : continue;

could be written as x *= ((x == y) ? 2 : 1), provided that you weren't actually trying to get loop-cycling behavior out of that continue. And

x == y ?: x /=2;

could be rewritten similarly. Though if you were actually looking toward IOCCC, then there are better obfuscation options available.

For the purpose asked about in this question, in which the result value of the conditional operator would not be used:

  • For a ? b : c without b you can use a && b, which will evaluate b if and only if a is true.
  • For a ? b : c without c you can use a || c, which will evaluate c if and only if a is false.

These expressions will have different values than a ? b : c, but that does not matter when the value is not used.

Without some exceptional circumstance to justify this, most experienced programmers would consider it bad practice.

GCC has an extension that uses the first operand for a missing second operand without evaluating it a second time. E.g. f(x) ? : y is equivalent to f(x) ? f(x) : y except that f is only called once.

Similar to the 'hyphen-ish' character of "-1" being called "unary minus", "?:" is called "trenary" because it requires 3 parts: the condition, the "true" case statement and the "false" case statement. To use "?:" you must supply 3 "terms".

Answering the question in the title, no, you cannot omit one part.

The following responds to "What can I do in these situations except:"

Given that your two examples show an interest in performing (or not) a mathematical operation on the variable 'x', here is a "branchless" approach toward that (limited) objective. ("Branchless" coding techniques seek to reduce the impact of "branch prediction misses", an efficiency consideration to reduce processing time.)

Note: the for() loop is only a "test harness" that presents 3 different values for 'y' to be compared to the value of 'x'. The variable 'n' makes more obvious your OP constant '2'. Further, as you are aware, performing multiplication OR division are two completely different operations. This example shows multiplication only. (Replace the '*' with '/' for division with the standard caveat regarding "division by zero" being undefined.) Depending on the probability of "cache misses" and "branch prediction" in modern CPUs, this seemingly complex calculation may require much less processing time than a 'true/false branch' that may bypass processing.

int n = 2; // multiplier

for( int y = 4; y <= 6; y++ ) { // three values for 'y'
    int xr = 5; // one value for 'xr'egular
    int xb = 5; // same value for 'xb'ranch

    (xr == y) ? xr *= n : 1; // to be legitimate C

    // when x == y the rhs becomes (n-1)*(1)+1 which equals n
    // when x != y the rhs becomes (n-1)*(0)+1 which equals 1 (identity)
    // Notice the rhs includes a conditional
    // and that the entire statement WILL be evaluated, never bypassed.
    xb *= ((n-1)*(xb==y))+1;

    printf( "trenaryX = %2d, branchlessX = %2d\n", xr, xb );
}

Output

trenaryX =  5, branchlessX =  5
trenaryX = 10, branchlessX = 10
trenaryX =  5, branchlessX =  5

I hope this makes clear that "trenary" means "3 part" and that this digression into "branchless coding" may have broadened your horizons.

You can use the fact that the result of comparison operators is an int with value 0 or 1...

x == y ? x*=2;
 x *= (x == y) + 1; // multiply by either 1 or 2

But a plain if is way more readable

if (x == y) x *= 2;

Actually, you shouldn't do this because as @user229044 commented, "if (x==y) do_something; is exactly what you should do here, not abuse the ternary operator to produce surprising, difficult-to-read code that can only cause problems down the line. You say "I need to know if that's possible", but why? This is exactly what if is for."

As in ternary operator without else in C, you can just have the third/second part of the ternary operator set x to itself, for example, you can just do:

x = (x == y ? x *= 2 : x);

or

x == (y ? x : x /= 2);
x == y ? x*=2 : 1;

The syntax requires all three parts... But, if you write code like this, you will lose popularity at the office...

Repeating for those who might have missed it: The syntax requires all three parts.

Related