如果您可以消除必须坚持使用 C99 的限制,那么自 C11 以来该语言内置了一个更好的解决方案来解决这个问题:
#include <stdio.h>
void f1(float x, double y, float * z) {
printf("inside f1\n");
}
void f2(int x, _Bool * y) {
printf("inside f2\n");
}
#define STATIC_IF(COND, ...) _Generic(&(int[(!!(COND))+1]){ 0 }, \
int(*)[2]: f1, \
int(*)[1]: f2) \
(__VA_ARGS__)
int main(void) {
float fl;
_Bool b;
STATIC_IF(sizeof(double) > 4, 0.0f, 1.0, &fl);
STATIC_IF(sizeof(double) > 128, 16, &b);
}
运算符基于_Generic
类型执行编译时选择。由于它基于类型进行选择,因此它也是唯一可以接受冲突类型的“参数”的语言级表达式,因为它的目的是根据输入解析正确类型的值。
这意味着您可以轻松地使用它在具有不兼容签名的两个函数之间进行选择,因为它将完全忽略通过匹配输入未选择的函数的类型;参数(适用于任何函数_Generic
返回)将仅根据成功匹配进行检查。
尽管_Generic
设计用于分派类型而不是值,但任何整数常量表达式都可以通过将其用作数组的大小来“转换为”类型。因此,在上面的宏中,我们创建了一个匿名数组(nb 这不是VLA),计数为 2(为真)或 1(为假),并针对指向该数组的指针的类型进行调度,以解析哪个要使用的两个不兼容的功能。
这肯定会在运行时减少到零,因为不仅条件是静态的,而且替代的“执行路径”甚至不会进行类型检查,因此首先无法为其生成代码。