0

I am trying to understand a code written by my professor. There's a line in the code that says

a = (b > c) ? c : b;

where a, b, and c are just float variables. This is my first time seeing that expression. I tried to google it but nothing came up. Any explanation or link to some explanation for this is welcomed. Thank you.

2 Answers2

5

That is a ternary expression. Ternary expressions take the form:

condition ? <result_if_true> : <result_if_false>

Ternary expressions can be translated to an if statement:

if (condition) {
    <result_if_true>;
} else {
    <result_if_false>;
}

An advantage of ternary expressions over the equivalent if statements is variable declaration. For example, the following if statement and ternary expression are equivalent, but it is clear which is more concise:

int seconds = 4;

// ===== USING IF STATEMENT =====
string secs_string;

if (seconds == 1) {
    secs_string = "second";
} else {
    secs_string = "seconds";
}

cout << "You have " << seconds << " "<< secs_string << " remaining." << endl;
// Output: You have 4 seconds remaining.


// ===== USING TERNARY EXPRESSION =====
string secs_string = (seconds == 1) ? "second" : "seconds";

cout << "You have " << seconds << " "<< secs_string << " remaining." << endl;
// Output: You have 4 seconds remaining.

Note that using an if requires a seprate declaration of the string outside of the if statement whereas with a ternary expression, this can be done inline.


Further Reading

Sumner Evans
  • 8,951
  • 5
  • 30
  • 47
  • Ternary expressions cannot really be translated into if statements because statements cannot be put inside of larger expressions. Note that the "ternary expression here is `condition ? : `. – juanchopanza Dec 03 '17 at 07:44
  • @juanchopanza well, there is always a way to desugar a ternary to an `if` statement. I agree, it may not be a direct correlation, but even something complex like: `x = a ? (b ? c : d) : (e ? f : g)` can be desugared to a few nested `if` statements. Additionally, something like `foo(x ? y : z)` can be desugared to `if (x) foo(y); else foo(z);` – Sumner Evans Dec 03 '17 at 07:47
  • There is no sugar to desugar here. Expressions and statements are very different things. You may replace code that uses an expression by equivalent code using if statements, but that does not mean that the expression is universally replaceable by the statement. – juanchopanza Dec 03 '17 at 07:52
  • Even assignment is an expression in C++ (guaranteed for built-ins, possible to break in user defined types), so you can use `variable = whatever` as a sub-expression. You can't do that with the ifs. – juanchopanza Dec 03 '17 at 07:53
  • @juanchopanza, is there a specific example where a ternary expression cannot be converted to an `if` statement? I've never run into one personally (maybe I've just not been coding for long enough). I understand that they are different conceptually, but to my knowledge, they basically compile to the same assembly. (Also, I find that the `if` translation to be an effective way of explaining ternary expressions to people who are unfamiliar with the syntax. That is, in part, why I chose to include it in my answer.) – Sumner Evans Dec 03 '17 at 07:58
  • You already have an example in your answer, the variable declaration. But even in the assignment expression above, you cannot replace the ternary expression by ifs: `variable = if ...`. Or, for example, `bar(foo(x ? y : z))`. The call to `foo` is not replaceable by a statement. – juanchopanza Dec 03 '17 at 08:05
  • @juanchopanza, I see where you are coming from. An `if` statement is never a "drop-in" replacement for a ternary expression. My point is that there is always an equivalent-result `if` statement (or combination thereof) for every ternary expression. – Sumner Evans Dec 03 '17 at 08:10
3

This is called the conditional operator, also referred to as the ternary operator. It's just an if-statement in compressed form.

a = (b > c) ? c : b;

has the same effect as

if (b > c) a = c; else a = b;
Silvio Mayolo
  • 62,821
  • 6
  • 74
  • 116
  • Worth noting that it is sometimes useful to use the ternary operator if you're trying to guide the compiler to use a conditional move. But, like all tips and tricks for optimization, this isn't guaranteed and may no longer even be true. – Tyler Dec 03 '17 at 07:08
  • @Tyler I'm not familiar with that pattern. Perhaps you should post it as an answer. – Silvio Mayolo Dec 03 '17 at 07:09
  • 2
    Strictly speaking, they are not the same – Passer By Dec 03 '17 at 07:11
  • @Silvio: Not really a pattern, just two different ways the compiler can translate an if on x86: either with explicit branching which conditionally changes the instruction pointer to different blocks to handle the conditions or as a conditional move (`cmov`) which doesn't change the IP and instead bundles the conditional into a single instruction. In low latency situations, and especially those in which uniform latency is desired, a `cmov` is preferred. – Tyler Dec 03 '17 at 07:13