gcc builtin: choose_expr
You can use the built-in function __builtin_choose_expr to evaluate code depending on the value of a constant expression. This built-in function returns exp1 if const_exp, which is an integer constant expression, is nonzero. Otherwise it returns exp2.
April 7, 2026
gcc builtin: choose_expr
Reqruies
- Compiler : gcc 3.1 or later
In this post, we will explore __builtin_choose_expr, one of the GCC built-in functions.
This function is not supported in C++ and is a feature available only in the C language.
This function is not supported in C++ and is a feature available only in the C language.
Its behavior is very similar to C's ternary operator (
However, the most important difference is that this operation is performed at compile-time, not at runtime.
? : operator).However, the most important difference is that this operation is performed at compile-time, not at runtime.
This built-in function was added in GCC version 3.1 through a patch by Aldy Hernandez.
GCC Documentation
Let's first look at the explanation from the official GCC documentation.
__builtin_choose_expr (const_exp, exp1, exp2)DocYou can use the built-in function __builtin_choose_expr to evaluate code depending on the value of a constant expression. This built-in function returns exp1 if const_exp, which is an integer constant expression, is nonzero. Otherwise it returns exp2.
This built-in function is analogous to the '? :' operator in C, except that the expression returned has its type unaltered by promotion rules. Also, the built-in function does not evaluate the expression that is not chosen.
For example, if const_exp evaluates to true, exp2 is not evaluated even if it has side effects...
Internal Implementation
Checking the GCC source code directly makes it easier to understand how this function works.
Below is a snippet from the
Below is a snippet from the
c-parser.c code in GCC 7.4.gcc/c/c-parser.cc
If you look closely at the code, you can see that it is internally implemented using a ternary operator.
Constraints: Constant Expressions
One important thing to note here is that the first argument must be a const_exp (constant expression).
In the C language, a standard
const variable is not treated as a constant expression, so it cannot be used as the first argument.Let's check the result when actually using a variable.
can we use the variables for the first argument?c
gcc version 7.4.0 –target=x86_64-linux-gnubash
As shown above, a compilation error occurs.
Therefore, you must use an actual constant expression as shown below.
Therefore, you must use an actual constant expression as shown below.
use const expr for the first argumentc
execution resultbash
If you check the assembly code, you can see that the values are already decided at compile-time.
assembly - x86_64 AT&Tbash
strings checkbash
You can confirm that __builtin_choose_expr has been completely replaced by
exp1 or exp2 respectively at compile-time.Practical Examples
Although it might seem useless due to the constraint that only constant expressions can be used, it can actually be utilized very effectively.
For example, you can write an
IS_MASKED macro that checks at compile-time whether a specific bit is set.e.g. maskedc
You can also find cases in the Linux kernel's
eBPF code where it is used alongside sizeof.e.g. sizeof in BPF (include/trace/bpf_probe.h)c
Return Type Characteristics
This built-in function differs significantly from a standard ternary operator in how it handles types.
While a standard ternary operator may result in implicit type promotion depending on the types of the operands, this builtin function maintains the type of the selected
exp1 or exp2 exactly as it is, without any promotion.check return typec
execution resultbash
Advanced Usage: Function Overloading
__builtin_choose_expr becomes even more powerful when combined with other built-in functions.
For example, combined with __builtin_types_compatible_p, you can implement something similar to function overloading based on argument types, which is not natively supported in C.
function overloading in cc
execution resultbash
Conclusion
__builtin_choose_expr might seem simple, but when applied in the right places, it is a useful tool that can reduce unnecessary code and lead to compile-time optimizations.
As a side note, standard C also allows implementing similar processing based on argument type or count using macros, which I hope to cover in another post if I get the chance.