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?
相关问题
- Multiple sockets for clients to connect to
- What is the best way to do a search in a large fil
- glDrawElements only draws half a quad
- Index of single bit in long integer (in C) [duplic
- Equivalent of std::pair in C
Compactness and the ability to inline an if-then-else construct into an expression.
The fact that the ternary operator is an expression, not a statement, allows it to be used in macro expansions for function-like macros that are used as part of an expression. Const may not have been part of original C, but the macro pre-processor goes way back.
One place where I've seen it used is in an array package that used macros for bound-checked array accesses. The syntax for a checked reference was something like
aref(arrayname, type, index)
, where arrayname was actually a pointer to a struct that included the array bounds and an unsigned char array for the data, type was the actual type of the data, and index was the index. The expansion of this was quite hairy (and I'm not going to do it from memory), but it used some ternary operators to do the bound checking.You can't do this as a function call in C because of the need for polymorphism of the returned object. So a macro was needed to do the type casting in the expression. In C++ you could do this as a templated overloaded function call (probably for operator[]), but C doesn't have such features.
Edit: Here's the example I was talking about, from the Berkeley CAD array package (glu 1.4 edition). The documentation of the array_fetch usage is:
and here is the macro defintion of array_fetch (note the use of the ternary operator and the comma sequencing operator to execute all the subexpressions with the right values in the right order as part of a single expression):
The expansion for array_insert ( which grows the array if necessary, like a C++ vector) is even hairier, involving multiple nested ternary operators.
Some of the more obscure operators in C exist solely because they allow implementation of various function-like macros as a single expression that returns a result. I would say that this is the main purpose why the
?:
and,
operators are allowed to exist, even though their functionality is otherwise redundant.Lets say we wish to implement a function-like macro that returns the largest of two parameters. It would then be called as for example:
The only way to implement this as a function-like macro would be
It wouldn't be possible with an
if ... else
statement, since it does not return a result value. Note)The other purpose of
?:
is that it in some cases actually increases readability. Most oftenif...else
is more readable, but not always. Take for example long, repetitive switch statements:This can be replaced with the far more readable
Please note that
?:
does never result in faster code thanif-else
. That's some strange myth created by confused beginners. In case of optimized code,?:
gives identical performance asif-else
in the vast majority of the cases.If anything,
?:
can be slower thanif-else
, because it comes with mandatory implicit type promotions, even of the operand which is not going to be used. But?:
can never be faster thanif-else
.Note) Now of course someone will argue and wonder why not use a function. Indeed if you can use a function, it is always preferable over a function-like macro. But sometimes you can't use functions. Suppose for example that
x
in the example above is declared at file scope. The initializer must then be a constant expression, so it cannot contain a function call. Other practical examples of where you have to use function-like macros involve type safe programming with_Generic
or "X macros".