_Generic() 宏不扩展
_Generic() macro not expanding
所以我正在尝试实现 "generic printing macro":
#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()
在翻译的时候展开呢?
顺便说一句:我不匹配哪个 )
?
_Generic
不是宏,而是primary expression (see also 6.5.1.1). As such it is evaluated at a later translation phase (7) than string concatenation (phase 6). See the standard, 5.1.1.2。简而言之:当编译器连接字符串时,_Generic
尚未计算。
您必须将转换后的值作为字符串参数传递给 printf
或使用格式字符串调用单独的 printf
作为值。保持宏较小的一种方法是使用辅助函数,您传递类型代码加上 union
中的实际值。然后该函数将使用 switch
进行转换和打印。或者您对每种类型使用不同的函数。当然还有各种选择。
好的,这是一个(不一定是最好的)方法:
#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
具有误导性,因为这些函数并不真正在 运行 时检查某些内容。更好的名字是例如"PRINT_VALUE".
所以我正在尝试实现 "generic printing macro":
#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()
在翻译的时候展开呢?
顺便说一句:我不匹配哪个 )
?
_Generic
不是宏,而是primary expression (see also 6.5.1.1). As such it is evaluated at a later translation phase (7) than string concatenation (phase 6). See the standard, 5.1.1.2。简而言之:当编译器连接字符串时,_Generic
尚未计算。
您必须将转换后的值作为字符串参数传递给 printf
或使用格式字符串调用单独的 printf
作为值。保持宏较小的一种方法是使用辅助函数,您传递类型代码加上 union
中的实际值。然后该函数将使用 switch
进行转换和打印。或者您对每种类型使用不同的函数。当然还有各种选择。
好的,这是一个(不一定是最好的)方法:
#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
具有误导性,因为这些函数并不真正在 运行 时检查某些内容。更好的名字是例如"PRINT_VALUE".