__builtin_choose_expr
是 GCC 编译器的内置函数,它允许在编译时根据条件表达式的值选择两个表达式其中之一。其语法结构如下:
__builtin_choose_expr(constant_expression, expression1, expression2)
这个内置函数根据第一个参数 constant_expression
的结果在 expression1
和 expression2
中选择一个。如果 constant_expression
是非零的(即,认为是 true
),则选择 expression1
; 如果是零(即,认为是 false
),则选择 expression2
。
constant_expression
必须是编译时可知的常量表达式,而不是运行时才能确定的值。
这个功能类似于C语言中的 ? :
三元条件运算符,但关键的区别在于 __builtin_choose_expr
是在编译时进行选择,这意味着只有被选中的那个表达式会被编译进最终的程序。下面是一个例子:
int main() {
int x = __builtin_choose_expr(1, 42, 0); // 由于条件为 true(1),所以 x 将被赋值为 42
int y = __builtin_choose_expr(0, 42, 0); // 由于条件为 false(0),所以 y 将被赋值为 0
return 0;
}
使用案例:
#define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b))
#define __TYPE_AS(t, v) __same_type((__force t)0, v)
#define __TYPE_IS_LL(t) (__TYPE_AS(t, 0LL) || __TYPE_AS(t, 0ULL))
#define __SC_LONG(t, a) __typeof(__builtin_choose_expr(__TYPE_IS_LL(t), 0LL, 0L)) a
__SC_LONG
宏的作用是基于传入的类型 t
是否与 long long
或 unsigned long long
兼容,来定义一个新的变量 a
。
首先,来看看这些宏的组成部分:
-
__same_type(a, b)
:这个宏使用了 GCC 的内置函数__builtin_types_compatible_p
来检查两个类型表达式a
和b
是否相同。typeof(a)
会获取a
的类型,同理typeof(b)
获取b
的类型。 -
__TYPE_AS(t, v)
宏:利用__force
宏将类型t
的值0
转换成t
类型,并检查它是否与变量v
的类型相同。 -
__TYPE_IS_LL(t)
宏:检查传入的类型t
是否与long long
(0LL
)或unsigned long long
(0ULL
)类型相同或兼容。 -
__SC_LONG(t, a)
:综合使用上述宏,根据t
的类型,选择适当的类型(long long
或者long
)来定义变量a
。
在 __SC_LONG
宏中,__builtin_choose_expr
函数基于 __TYPE_IS_LL
宏的结果选择 0LL
或 0L
,并用 __typeof
来获取该结果的类型。如果 t
与 long long
或 unsigned long long
类型兼容,则变量 a
的类型就会是 long long
;否则,变量 a
的类型就会是 long
。
所以简单地说,__SC_LONG
宏就是根据 t
的类型来声明变量 a
,让 a
成为 long long
或 long
类型中适合 t
类型的一个。这样的设计允许代码根据不同平台上类型大小的差异来选择合适的类型,这在跨平台编程时是非常有用的,尤其是在你需要处理不同数据模型(如 32 位与 64 位系统)时。