5

Is it possible to write the equivalent compound "if" statement using the "?" operator in C? I want to write an "if - else if - else" statement and was wonder if I could utilize the "?" operator.

I believe the regular syntax for using "?" would be something like

foo = (bar == 42) ? answerToEverything : useless;

If I wanted to rewrite the following statement in one line using the "?" operator, could I do that? How?

if(bar == 42) {
  foo = answerToEverything;
} 
else if(bar == 23) {
  foo = bigMike;
} 
else foo = useless;
Deduplicator
  • 44,692
  • 7
  • 66
  • 118
  • `(bar==42) ? foo = answerToEverything : (bar==23) ? foo = bigMike : foo = useless` – Kevin L Jul 31 '14 at 16:58
  • 7
    I think nesting ternary operators is kind of ugly. What you have there is perfectly fine IMO – Ben Jul 31 '14 at 16:58
  • I also agree with @Ben. What is your goal in writing it using the conditional operator (often confusingly named 'ternary operator')? –  Jul 31 '14 at 17:01
  • 1
    Why don't you just use a `switch` statement? – Oliver Charlesworth Jul 31 '14 at 17:05
  • I would say "Why rewrite it?" The ternary operator mechanism is handy in a few cases where it hides details you don't really need to worry about, but using it where there is any complexity around its use is far too apt to lead to confusion and bugs. Just say "No!" to ternary. – Hot Licks Jul 31 '14 at 17:52

8 Answers8

13
foo = 
    (bar == 42) ? answerToEverything :
    (bar == 23) ? bigMike :
    useless;
Bill Lynch
  • 80,138
  • 16
  • 128
  • 173
  • I might have to take my comment back, this actually looks kind of neat. Any reason to not overuse this? – Ben Jul 31 '14 at 16:59
  • 3
    @Ben: I usually use this when I want `foo` to be const and I'd like the code containing the result to have spatial locality. – Bill Lynch Jul 31 '14 at 17:00
  • 2
    @Ben: I'd also argue that the other answers are formatting their code terribly. I wouldn't use this if I formatted it like they did. – Bill Lynch Jul 31 '14 at 17:02
  • 1
    @Ben: I'm a fan of the ternary operator but nesting it is a sure-fire way to confuse yourself in the future and enrage your coworkers! – maerics Jul 31 '14 at 17:06
  • 3
    +1 For demonstrating that **proper formatting matters**. – Deduplicator Jul 31 '14 at 17:08
  • 1
    +1 for providing a readable version. – Andy Thomas Jul 31 '14 at 17:11
  • This sort of thing can work nicely syntax-wise for longer switches with all single-line statements. I'm not sure how it interacts with compiler optimizations, though. – chris Jul 31 '14 at 17:14
  • The value of good identation – Jack Jul 31 '14 at 17:40
  • 2
    The reason for not doing that is that it conceals the nesting that is present, and you still have to "parse" it to understand it. With nested ifs your eyes "parse" the structure for you (if it's decently formatted), before you even begin to look at the details. I mean, the above looks "neat", but, honestly, can you really look at it and tell what it does? – Hot Licks Jul 31 '14 at 17:53
  • 1
    After verifying the precedence once, it can become an immediately recognizable idiom. In terms of visual parsing, *with short expressions* it is at least as readable as nested ifs, if not more so. – Andy Thomas Jul 31 '14 at 18:08
6

Yes, you can, but it's ugly and hard to understand!

I would advise using the multiline form, since it's easier to comprehend:

if (bar == 42) {
  foo = answerToEverything;
} else if (bar == 23) {
  foo = bigMike;
} else {
  foo = useless;
}

But, if you really want to make your code difficult to read:

foo = (bar == 42)
  ? answerToEverything
  : (bar == 23)
      ? bigMike
      : useless;

Of course, feel free to format with whitespace as you see fit.

maerics
  • 151,642
  • 46
  • 269
  • 291
  • 1
    Better formatting like sharth demonstrates makes it beautiful. – Deduplicator Jul 31 '14 at 17:05
  • 3
    IMO the above formatting is better than sharth's since it actually reveals the structure, whereas sharth's conceals it. The purpose of formatting is not to look pretty, but to make structure apparent. – Hot Licks Jul 31 '14 at 17:56
4

Yes, you can do this, as shown below.

However, it is frequently considered bad style to nest conditional operators. This can harm readability.

foo = (bar == 42) 
  ? answerToEverything
  : ((bar==23) ? bigMike : useless );
Andy Thomas
  • 84,978
  • 11
  • 107
  • 151
  • See also the accepted answer, which shows how to get *both* nested conditionals *and* readability, at least for short expressions. – Andy Thomas Aug 10 '18 at 15:38
2

It is. You can just keep stacking ternary operator expressions at the tail:

foo = (bar == 42) ? answerToEverything : ( (bar==23) ? bigMike : useless);

But of course, readability is what matters the most, so you may be better of using if statements, or even better if possible, switch-case statements:

switch (bar) {
    case 42: foo = answerToEverything; break;
    case 23: foo = bigMike; break;
    default: foo = useless;
}
E_net4
  • 27,810
  • 13
  • 101
  • 139
  • I'm so late to this party....nested ternary statements -- this is some of the caraziest looking syntax I've seen. Thanks for explaining this using `switch` statement. Is the nested ternary faster than switch? – Chris22 Aug 10 '18 at 02:22
  • 1
    @Chris22 That will ultimately depend on your particular case and on how the compiler has optimized it. Usually, a `switch` statement with many `case` clauses is implemented with a look-up table rather than an exhaustive check. If performance really matters here, consider measuring the difference between the two. – E_net4 Aug 10 '18 at 10:11
  • thanks, I'll be sure to measure the diff between the two. I asked because `switch` is generally faster than a longer list of `if` statements, so I was wondering if the nested ternary was "generally" faster than all others. It's not that easy to read if it's long (_during a code review, I came across this syntax, containing 5+ nested conditions_), so I was wondering why the coder used it instead. – Chris22 Aug 10 '18 at 14:48
2

You have already received several correct answers, but all of the ones posted so far contain excessive (). (Interestingly enough, their authors boldly discard the () around the entire nested ?: operators, but sheepishly insist on keeping () around the == comparison. Myself, I'd have more doubts about discarding the former than the latter.) Anyway, since we are already trying to be living on the edge with regard to taking precedence and associativity risks, here's my version

foo = 
  bar == 42 ? answerToEverything :
  bar == 23 ? bigMike :
  useless;

One [minor] problem with implementing it through the ?: operator is that typically you won't be able to see which path was taken in step-by-step debugger. Most (if not all) debuggers will treat the above as an atomic operation and execute it in one step. (More precisely, most compilers will generate debug info that treats it as an atomic operation.) With if-ladder approach you will explicitly see what path was taken.

AnT stands with Russia
  • 312,472
  • 42
  • 525
  • 765
  • The sample code appears to be the same as @sharth's previous, pretty answer, but with the removal of parantheses around the conditions. Parantheses can be valuable for visual grouping to humans even when they're not necessary for the compiler. I personally find sharth's version more readable. – Andy Thomas Jul 31 '14 at 17:09
  • @AndyThomas: I personally upvoted this answer. And my upvote stands even more confidently with the addition of the second paragraph. – Bill Lynch Jul 31 '14 at 17:11
  • @Andy Thomas: @sharth answer is exactly where I stole the original version of the code. Note that I have no intent to claim that my version is "better" or "more correct". I just wanted to additionally illustrate the fact that the `()` around the comparison is excessive. However, in this specific case (i.e. comparison part of `?:` operator) I *personally* do believe that excessive `()` are annoying and code reads better without it (as long as it is properly formatted). – AnT stands with Russia Jul 31 '14 at 17:13
1

If I understand your question, then yes with a nested ternary, like

foo = (bar == 42) ? answerToEverything : ((bar == 23) ? bigMike : useless);

Please note, I do not recommend you use a nested ternary - it's very difficult to read.

Elliott Frisch
  • 198,278
  • 20
  • 158
  • 249
0

you could use compound ?: statement.

like preceding code could be the following:

(bar == 42) ? (foo = answerToEverything): ((bar == 23) ? (foo = bigMike) : (foo = useless));
Josan
  • 692
  • 1
  • 5
  • 27
0

I believe that this should do what you want. It is essentially combining two of the compound if statements. The second one will only get evaluated if the first one evaluates false.

foo = (bar == 42) ? "answerToEverything" : ((bar == 23) ? "bigMike" : "useless");

I ran this in an online compiler and made foo a string and bar an int and it behaved as expected.

andrewalexander
  • 153
  • 1
  • 7