The ternary (conditional) operator in C

2019-01-03 06:04发布

What is the need for the conditional operator? Functionally it is redundant, since it implements an if-else construct. If the conditional operator is more efficient than the equivalent if-else assignment, why can't if-else be interpreted more efficiently by the compiler?

15条回答
家丑人穷心不美
2楼-- · 2019-01-03 06:45

Sometimes the ternary operator is the best way to get the job done. In particular when you want the result of the ternary to be an l-value.

This is not a good example, but I'm drawing a blank on somethign better. One thing is certian, it is not often when you really need to use the ternary, although I still use it quite a bit.

const char* appTitle  = amDebugging ? "DEBUG App 1.0" : "App v 1.0";

One thing I would warn against though is stringing ternaries together. They become a real
problem at maintennance time:

int myVal = aIsTrue ? aVal : bIsTrue ? bVal : cIsTrue ? cVal : dVal;

EDIT: Here's a potentially better example. You can use the ternary operator to assign references & const values where you would otherwise need to write a function to handle it:

int getMyValue()
{
  if( myCondition )
    return 42;
  else
    return 314;
}

const int myValue = getMyValue();

...could become:

const int myValue = myCondition ? 42 : 314;

Which is better is a debatable question that I will choose not to debate.

查看更多
姐就是有狂的资本
3楼-- · 2019-01-03 06:47

It's crucial for code obfuscation, like this:

Look->       See?!

No
:(
Oh, well
);
查看更多
走好不送
4楼-- · 2019-01-03 06:49

Ternary operator may be of more performance than a normal if else clause, this may be critical in embedded applications but also compiler optimization may collapse this difference.

查看更多
放我归山
5楼-- · 2019-01-03 06:51

Some of the other answers given are great. But I am surprised that no one mentioned that it can be used to help enforce const correctness in a compact way.

Something like this:

const int n = (x != 0) ? 10 : 20;

so basically n is a const whose initial value is dependent on a condition statement. The easiest alternative is to make n not a const, this would allow an ordinary if to initialize it. But if you want it to be const, it cannot be done with an ordinary if. The best substitute you could make would be to use a helper function like this:

int f(int x) {
    if(x != 0) { return 10; } else { return 20; }
}

const int n = f(x);

but the ternary if version is far more compact and arguably more readable.

查看更多
Juvenile、少年°
6楼-- · 2019-01-03 06:53

Since no one has mentioned this yet, about the only way to get smart printf statements is to use the ternary operator:

printf("%d item%s", count, count > 1 ? "s\n" : "\n");

Caveat: There are some differences in operator precedence when you move from C to C++ and may be surprised by the subtle bug(s) that arise thereof.

查看更多
该账号已被封号
7楼-- · 2019-01-03 06:53

like dwn said, Performance was one of its benefits during the rise of complex processors, MSDN blog Non-classical processor behavior: How doing something can be faster than not doing it gives an example which clearly says the difference between ternary (conditional) operator and if/else statement.

give the following code:

#include <windows.h>
#include <stdlib.h>
#include <stdlib.h>
#include <stdio.h>

int array[10000];

int countthem(int boundary)
{
 int count = 0;
 for (int i = 0; i < 10000; i++) {
  if (array[i] < boundary) count++;
 }
 return count;
}

int __cdecl wmain(int, wchar_t **)
{
 for (int i = 0; i < 10000; i++) array[i] = rand() % 10;

 for (int boundary = 0; boundary <= 10; boundary++) {
  LARGE_INTEGER liStart, liEnd;
  QueryPerformanceCounter(&liStart);

  int count = 0;
  for (int iterations = 0; iterations < 100; iterations++) {
   count += countthem(boundary);
  }

  QueryPerformanceCounter(&liEnd);
  printf("count=%7d, time = %I64d\n",
         count, liEnd.QuadPart - liStart.QuadPart);
 }
 return 0;
}

the cost for different boundary are much different and wierd (see the original material). while if change:

 if (array[i] < boundary) count++;

to

 count += (array[i] < boundary) ? 1 : 0;

The execution time is now independent of the boundary value, since:

the optimizer was able to remove the branch from the ternary expression.

but on my desktop intel i5 cpu/windows 10/vs2015, my test result is quite different with msdn blog.

when using debug mode, if/else cost:

count=      0, time = 6434
count= 100000, time = 7652
count= 200800, time = 10124
count= 300200, time = 12820
count= 403100, time = 15566
count= 497400, time = 16911
count= 602900, time = 15999
count= 700700, time = 12997
count= 797500, time = 11465
count= 902500, time = 7619
count=1000000, time = 6429

and ternary operator cost:

count=      0, time = 7045
count= 100000, time = 10194
count= 200800, time = 12080
count= 300200, time = 15007
count= 403100, time = 18519
count= 497400, time = 20957
count= 602900, time = 17851
count= 700700, time = 14593
count= 797500, time = 12390
count= 902500, time = 9283
count=1000000, time = 7020 

when using release mode, if/else cost:

count=      0, time = 7
count= 100000, time = 9
count= 200800, time = 9
count= 300200, time = 9
count= 403100, time = 9
count= 497400, time = 8
count= 602900, time = 7
count= 700700, time = 7
count= 797500, time = 10
count= 902500, time = 7
count=1000000, time = 7

and ternary operator cost:

count=      0, time = 16
count= 100000, time = 17
count= 200800, time = 18
count= 300200, time = 16
count= 403100, time = 22
count= 497400, time = 16
count= 602900, time = 16
count= 700700, time = 15
count= 797500, time = 15
count= 902500, time = 16
count=1000000, time = 16

the ternary operator is slower than if/else statement on my machine!

so according to different compiler optimization techniques, ternal operator and if/else may behaves much different.

查看更多
登录 后发表回答