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.
Its behavior is very similar to C's ternary operator (? : 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)
Doc

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.

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 c-parser.c code in GCC 7.4.
gcc/c/c-parser.c
c
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-gnu
bash
As shown above, a compilation error occurs.
Therefore, you must use an actual constant expression as shown below.
use const expr for the first argument
c
execution result
bash
If you check the assembly code, you can see that the values are already decided at compile-time.
assembly - x86_64 AT&T
bash
strings check
bash
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. masked
c
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 type
c
execution result
bash

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 c
c
execution result
bash

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.
Jooojub
System S/W engineer
Explore Tags
Series
    Recent Post
    © 2026. jooojub. All right reserved.