所以我正在尝试实现“通用打印宏”:
#include <stdio.h>
#include <float.h>
#define CHECK(x) printf(#x " =" \
_Generic((x), float: double: "%f",\
int: "%d",\
default: "Cannot print this with CHECK(x)")\
, x)
int main(void){
CHECK(FLT_RADIX);
return 0;
}
这给了我错误:
main.c:11:2: error: expected ')'
CHECK(FLT_RADIX);
^
main.c:5:3: note: expanded from macro 'CHECK'
_Generic((x), float: double: "%f",\
^
main.c:11:2: note: to match this '('
main.c:4:24: note: expanded from macro 'CHECK'
#define CHECK(x) printf(#x " =" \
^
1 error generated.
运行clang main.c -E
后,输出为:
int main(void){
printf("FLT_RADIX" " =" _Generic((2), float: double: "%f", int: "%d", default: "Cannot print this with CHECK(x)") , 2);
return 0;
}
那么如何在翻译期间扩展_Generic()
?
BTW:哪个)
我不匹配?
答案 0 :(得分:8)
_Generic
不是宏,而是primary expression(另请参阅6.5.1.1)。因此,它在后来的转换阶段(7)中进行评估,而不是字符串连接(阶段6)。请参阅标准5.1.1.2。简而言之:当编译器连接字符串时,尚未评估_Generic
。
您必须将转换后的值作为字符串参数传递给printf
,或者使用格式字符串为该值调用单独的printf
。保持宏较小的一种方法是使用辅助函数 - 传递类型代码加上union
中的实际值。然后,该函数将使用switch
进行转换&amp;打印。或者您为每种类型使用不同的功能。当然有各种各样的选择。
好的,这是一个(不一定是最好的)方法:
#define CHECK(x) _Generic((x), double: print_as_double(#x, x), \
float: print_as_double(#x, x),
int: print_as_int(#x, x), \
default: printf("Cannot print this with CHECK(x)") )
void print_as_float(const char *name, double value)
{
printf("%s = %lf", value);
}
...
请注意,您无法在泛型关联中组合不同的类型名称,这就是我必须拆分float
和double
条目的原因。
旁注:名称CHECK
具有误导性,因为函数在运行时并未真正检查某些内容。一个更好的名字将是例如&#34; PRINT_VALUE&#34;