-5

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.

user174174
  • 119
  • 1
  • 5
  • 3
    `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... – Fe2O3 Sep 07 '22 at 00:40
  • 7
    Why don't you want to use an `if` statement? – ad absurdum Sep 07 '22 at 00:41
  • Ternary operator is generally used in conditional assignment. You are trying to modify `x` based on a condition, right? – eventHandler Sep 07 '22 at 00:42
  • 7
    It's called the ternary operator for a reason: it must have three expressions taken in as an argument. You want to check a condition and, if it's true, do something. That's what an if statement is for. Otherwise you are asking how to use a hammer as a drill. – bream Sep 07 '22 at 00:43
  • @adabsurdum I need to know if that's possible with ternary operator, and btw the ternary-operator tag exists but somehow it keeps disappearing when I add it to my question :-? – user174174 Sep 07 '22 at 00:47
  • 5
    `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. – user229044 Sep 07 '22 at 00:48
  • @eventHandler yes, exactly. – user174174 Sep 07 '22 at 00:51
  • 2
    Usually a conditional operator is used in an expression, and it evaluates to some value whether or not the expression preceding `?` is true. For example, `printf("%s\n", num % s == 0 ? "even" : "odd");`. You can't do this with an `if` statement. Conversely, when you only want to accomplish some action when a condition is true, and do nothing otherwise, `if` statements are appropriate, and expected. Hacks which try to use the conditional operator as an `if` statement will at best obfuscate your code. – ad absurdum Sep 07 '22 at 00:56
  • 2
    You can't hammer the ternary operator into a binary operator, but there are already binary operators that do what you're trying to do: `x == y && (x /= 2)`. This is extremely non-obvious code, and should never pass code review. – user229044 Sep 07 '22 at 00:59
  • 1
    "_but somehow it keeps disappearing when I add it to my question_" -- `ternary-operator` is a tag synonym of `conditional-operator`, which your question does have. Note that the C Standard calls the `?:` syntax the conditional operator. – ad absurdum Sep 07 '22 at 01:02
  • @user229044 I'm not trying to abuse or surprise , it's there because of a reason, if I'm not mistaken it's a shorthand for if(...)...;else...; So why I just can't use it as if? – user174174 Sep 07 '22 at 01:05
  • 1
    @user229044 If only that worked in C, that would be a great tool to shorten code, (like sh-scripts). You can only do that where a conditional is required. – Neil Sep 07 '22 at 01:05
  • 7
    @user174174 It's not a shorthand for `if/else`. Using it as such **is** an abuse of a language feature. It has completely different semantics. You use ternary when you need something like `variable = condition ? value1 : value2`. You can't substitute in an `if` there, because `if` statements are not expressions that yield a value. – user229044 Sep 07 '22 at 01:06
  • 1
    @user229044 The OP asked if it is possible to omit 33% of the "?:" expression. You've chosen to delete my response that showed it was possible to remove 100% of the "?:" expression without resorting to `if/else` as per the OP... Do you need more coffee? – Fe2O3 Sep 07 '22 at 01:16
  • 3
    @Fe2O3 OP is pretty clearly interested in the general case, not in refactoring one specific case to hide the conditional inside a larger bit of math that *only* works for one of their cases. How was your answer helpful in the other division case, or in the clearly stated general case, `if (x == y) do_something;`? Where is `do_something` in your answer? This isn't codegolf. The goal is not to show off clever answers that don't actually help the OP in any way. – user229044 Sep 07 '22 at 01:21
  • 5
    @user229044: Are there guidelines about moderators deleting answers to questions in which they are participating in discussion in the comments? – Eric Postpischil Sep 07 '22 at 01:26
  • @user229044 The `do_something` in "functional programming" is "do this without branching" (cache misses)... The example shown in my answer corresponded to the OP "multiply" operation. Of course, if the operation is to divide, one uses '/' instead of '*'... There seems to be another answer below that has completely omitted the "?:" expression in that "solution"... Even handed, are we? – Fe2O3 Sep 07 '22 at 01:27
  • 1
    An expression using the conditional operator is *evaluated* to produce a value. What value do you expect for a result if you omit the second part and the controlling expression is true? Or if you omit the third part and the controlling expression is false? – John Bollinger Sep 07 '22 at 01:40
  • @user229044 infact Fe2O3 and ad absurdum comments were very helpfull and I'll be glad if you provide some examples where if can't be used instead of ?: – user174174 Sep 07 '22 at 01:43
  • 1
    @user174174 -- I provided an example of someplace that you can't use `if` in my second comment above. You can use the conditional operator `?:` anyplace you can use an expression, e.g., right-hand side of assignments, or in function calls (as in the `printf` example above). You can't use `if` statements in place of an expression. In other words, an expression evaluates to a value, but a statement does not. – ad absurdum Sep 07 '22 at 01:47
  • 4
    A deleted answer to this question is being [discussed on Meta](https://meta.stackoverflow.com/q/420236/208273) – Ryan M Sep 07 '22 at 01:49
  • 1
    A side note: community guidelines do not require an explanation for downvotes, though you are always welcome to ask how your question could be improved. – Ryan M Sep 07 '22 at 01:49
  • 3
    @EricPostpischil There aren't, as there's no conflict of interest there. It'd be one thing if the moderator had a competing answer, but that's not the case here. There's no reason for a moderator to refrain from both taking action on a question's answers and commenting on the question or other answers - for one thing, moderators are best equipped to take action on questions whose subjects they're familiar with. – Ryan M Sep 07 '22 at 01:53
  • 1
    @user174174 The entire point of `?:` is that it resolves to a value, while an `if` statement doesn't. If you're not using the value `?:` resolves to, you are probably misusing it, and producing code that is hard to read and understand because it doesn't conform to the expectations of virtually all programmers. All subsequent readers will look at your use of `?:` and waste time trying to figure out what you're doing and why, because it's such a strange and atypical use of that operator. They, (and we) will have no idea why you aren't using `if`, as it is the perfect and correct solution here. – user229044 Sep 07 '22 at 03:32

6 Answers6

4

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.

John Bollinger
  • 160,171
  • 8
  • 81
  • 157
  • 1
    Re "*If you're shooting for an entry in the International Obfuscated C Code Contest [...] *`x *= (x == y) ? 2 : 1`*", That's actually pretty clean. How about `x *= (x == y) + 1` – ikegami Sep 07 '22 at 04:52
  • Indeed so, @ikegami. I thought of that, but it doesn't use the the conditional operator, so I would account it among the "better obfuscation options available". – John Bollinger Sep 07 '22 at 12:01
  • @JohnBollinger "Or perhaps poor style is the point?" definitely not the case with me. Poor style and/or coding 'smart'. – user174174 Sep 08 '22 at 01:13
1

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.

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
  • Re "*For `a ? b : c` without `b` you can use `a && b`*", That only true if `b` is `0` or `1`. [Demo](https://godbolt.org/z/jrWaj4jTc) – ikegami Sep 07 '22 at 01:41
  • Re "*For `a ? b : c` without `c` you can use `a || b`*", That's only true if `c` is `0` or `1`. – ikegami Sep 07 '22 at 01:41
  • 1
    @ikegami: Read the answer. It says the expressions do not have the same values as the originals. OP can use them in place of the originals because they are not using them for their values, as evidenced by the fact an absent expression would not have a value. – Eric Postpischil Sep 07 '22 at 02:34
  • 1
    I read it a couple of times looking for that, but I missed that paragraph each time, I guess. That said, it makes no sense to use the conditional operator and discard the results. Just like it doesn't make sense to use `&&` and discard the results. – ikegami Sep 07 '22 at 02:51
  • I'll "forward" the moderator's comment about my "answer" that has been suppressed. "This doesn't answer the question, which was not at all about removing the ternary operator." Funny world. Pays to have powerful friends, Who'd have thought? – Fe2O3 Sep 07 '22 at 02:54
  • 2
    Fe2O3, @user229044 indeed made a mistake. – ikegami Sep 07 '22 at 02:54
  • @ikegami Thank you. `:-)` Although I will be the first to admit that "that answer" of mine did ALSO not use "?:"... Focussed on the "What can I do" line of the OP and the tendered "mathematical" operations... Thank you, though! `:-)` – Fe2O3 Sep 07 '22 at 02:55
  • @ikegami: The answer nowhere contradicts itself. It does not say the new expressions have the same values as the originals nor that they can be used everywhere the originals would be used (although that would be nowhere, since they will not compile). It says “you” can use them in place of the originals, meaning the OP ( or similarly situated reader) in the context of the question can use them for the purpose asked about in the question. – Eric Postpischil Sep 07 '22 at 02:56
  • Either their not equivalent, or you suggesting using `&&` or `||` and discarding the results. Either way, bad. – ikegami Sep 07 '22 at 03:52
  • 1
    @ikegami: Once again, read the answer. Discarding the result is explicitly stated, not just suggested. This is because the question posits a construct (`x == y ? x*=2;` or `x == y ? x/=2;`) that will not be used for its result, because it has no result in one case. The answer fits the question. If you do not like it, blame the question. This answer answers the question asked and advises it is bad practice. – Eric Postpischil Sep 07 '22 at 09:08
  • @ikegami: I updated the answer to clarify the alternatives are solely for the situation asked about in the question. Does that satisfy your issue? – Eric Postpischil Sep 08 '22 at 11:59
0

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.

Fe2O3
  • 6,077
  • 2
  • 4
  • 20
0

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;
pmg
  • 106,608
  • 13
  • 126
  • 198
-1
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.

Ryan M
  • 18,333
  • 31
  • 67
  • 74
Fe2O3
  • 6,077
  • 2
  • 4
  • 20
  • Since social/meta content is noise, a reasonable & likely improving edit is to end this after "The syntax requires all three parts." If you are repeating yourself and `emphasizing` then you yourself seem to agree you have already gone wrong. Moreover you could help the reader by explaining what the code does & this may indeed suit their needs, although it's not clear really what the asker wants, and that should be addressed via comment before answers. – philipxy Sep 07 '22 at 04:54
  • @philipxy The OP title is self-explanatory. So too, imho, is this answer. – Fe2O3 Sep 07 '22 at 05:41
-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);
Nathan Jiang
  • 131
  • 1
  • 9
  • 2
    You could factor out the assignment and just produce `x = (x == y ? x : x / 2)`, but you really shouldn't. – user229044 Sep 07 '22 at 00:51