Ternary operators made easy

One of the great features of the C language is the ternary operator.
It’s a wonderful tool (can be used as both an lvalue and rvalue; the only way to conditionally initialize a constant),
but reading deeply nested ternary operators can be quite difficult.

int i = a > 10 ? ( a < 100 ? (a - 66) : a + 66) : a / 2;

However, if you apply special formatting, everything becomes much clearer:

int i = a > 10 ? ( a < 100 ? (a - 66)
                           : a + 66)
               : a / 2;

How do you read this? Very easily.

  1. Read from left to right until you hit a question mark.
  2. If the answer is "yes", keep moving to the right — go back to step 1.
    If the answer is "no", move downward from the question mark to the first colon.
  3. If there's still more to read, go back to step 1.

Hope this help :slight_smile:

2 Likes

Why do some programmers feel the need to write code that is practically impenetrable and prone to error and misinterpretation when in most cases if/else can be used to produce the same result ?

3 Likes

As I said, sometimes it is very useable as it can be both lvalue and rvalue:
(just as an example)

(a > 0 ? object1 : object2)->method()

or, this is the only way to initialize a constant conditionally:

const int a = have_external_ram ? 666 : 999;

But I posted it to address "impenetrable code, prone to errors": proper formatting makes it simple and readable.

Not sure you second formatting makes it better...

I would prefer

int i = a / 2;

if (a > 10) {
  if (a < 100) i = a - 66;
  else i = a + 66;
}

true, it has its usage. Just need to balance with readability and maintainability.

Hi @vvb333007 ,

I agree with @UKHeliBob , @J-M-L ... and ultimately with yourself as your last post seems to be in line with them: If you have to split a ternary operator into three lines to make it readable, you have freedom, power and clarity if/else/else if gives.

I particularly use the ternary -and I've been gratefull since they included it in C++- for situations and commands where a different logical outcome makes you write the same code with a minimal difference, like addition instead of substraction, etc.

Something as simple as:

int inputValA{};

[...];

digitalWrite(pinA, (inputValA > 10)?HIGH:LOW);

Going further in complexity, in my opinion, is like extending a bit logical operation to 240 characters just not to build it in several lines... then you have to catch that skinny | in the spaghetti plate of I's (uppercase I) and l's (lowercase L) in variable names, ('s and )'s...

Good Luck!

Gaby.//

if you're going thru the trouble of formating wouldn't consistently putting the then and else statements on separate lines make more sense

    int i = a > 10
                ?  (a < 100
                    ? (a - 66)
                    : a + 66)
                : a / 2;

1 Like
// Hardly readable max(a,b,c)
    largest = (a > b) ? ((a > c) ? a : c) : ((b > c) ? b : c);

With proper formatting & reading rules:

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

Question mark or ternary operator?

this one: "?"

If:

c = 0;

if (a > 10 && a < 99) {

  if (b > 10 && b < 99) {
    c += (a - b);
  } else if (b > 100 && b < 1000) {
    c += (10*a - b);
  } else
    c += b;

} else 
  c += a;
}

?:

c += (a>10 && a<99) ? (b>10 && b<99 ? a - b
                                    : (b>100 && b<1000 ? 10*a - b
                                                       : b))
                    : a;

Hi @gcjr ,

Thank you, thank you, thank you very much!!.

I feel so lonely when I compose a message and have to control the hardwired temptation of describing the structure as a if - then - else !!!!

You've made my day!!

Sorry, back to topic, please don't hit me moderator!!

Gaby.//

Prefer to keep a question mark on the same line with logic statement :slight_smile:

'?' of the above.

You start from the left to the right, until you hit first "?". Then, depending on the answer to this "?" you either continue to the right (answer is YES) or, go straigh down until you hit first ":", and then continue to the right

1 Like

The more times you have to explain it and use a particular layout to go with it the more that I am convinced not to use nested ternary operators

7 Likes

Think of a positive side: if you have to dig into someone's code with lots of ?: operators, you can rearrange it so it becomes easily readable :smiley:

most experienced programmers recognize code patterns and immediately understand what is being done. There's no need for an experienced programmer to rearrange the code, except when someone writes it in an unconventional way.

1 Like

In the past, when C++ compilers had less advanced optimizers, the ternary operator condition ? expr1 : expr2 was useful because it often produced more efficient code than using a full if-else statement. This efficiency came from two key reasons.

➜ the ternary operator is an expression, not a statement, so the compiler could better inline the code and avoid jumps or extra control flow logic. This led to fewer instructions and better use of CPU pipelines, especially on simpler architectures.

➜ since the ternary operator directly returns a value, it allowed developers to write concise code that assigned or returned a value in a single expression, avoiding duplicated code or separate variable declarations that compilers at the time struggled to optimize away.

So the ternary operator gave programmers finer control over performance-critical code in ways the compilers couldn't yet handle automatically.

Today, modern C++ compilers have highly advanced optimizers that can analyze control flow, remove dead code, inline functions, and perform branch prediction-aware transformations. Because of this, the performance difference between a ternary operator and an equivalent if-else statement has largely disappeared in most cases.

Compilers can now recognize simple conditional patterns and generate the same efficient machine code regardless of whether a ternary or an if-else is used, as long as the semantics are the same. They can also eliminate redundant assignments, fold constants, and even move computations out of branches if safe.

==> the choice between a ternary operator and if-else is now mainly about readability and style, not performance.

PS/ As OP explained, the ternary operator is indispensable or super useful in contexts that require a single expression, such as initializing const, constexpr, references, or members, as well as in return statements / compact lambda bodies, default arguments, and macros, where if-else statements are syntactically invalid.

5 Likes

Since I have no idea what they are I probably won't be using ternary operators. I also don't see any of this in the Arduino language reference.

it can only be an rvalue. It can be an lvalue as a condition in many other expressions