Home > Back-end >  C ternary operator, can I omit one part?
C ternary operator, can I omit one part?

Time:09-07

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;

CodePudding user response:

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 in 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.

CodePudding user response:

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, if you are discarding the result, that does not matter.

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.

CodePudding user response:

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.

CodePudding user response:

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 = -, branchlessX = -\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.

CodePudding user response:

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