_Generic() 中的语句而不是表达式
Statements rather than expressions inside _Generic()
我需要 select 语句而不是 _Generic()
中的表达式。我知道我可以将它们放在函数中,但我更喜欢保存函数调用并改用宏。我知道另一种可能性是将语句转换为表达式的 GNU 扩展,但如果可能的话我宁愿不使用扩展。
我需要的是这样的:
#define FLOATWORK(X) do{ \
dostuff; \
dostuff; \
dostuff;}while(0)
#define DOUBLEWORK(X) do{ \
dostuff; \
dostuff; \
dostuff;}while(0)
#define GENERICWORK(X) _Generic((X), float: FLOATWORK(X), double: DOUBLEWORK(X))
我想到的另一种可能性是在我的宏中使用逗号运算符,试图将语句转换为带有逗号运算符的表达式。但是,我需要在宏中使用 switch/case
,并且 switch/case
不能是表达式 AFAIK。
那么,总而言之,我能否在不将宏语句放在函数中并且不使用 GCC 表达式语句扩展的情况下实现这一点?
不,你不能,因为它们需要是表达式。但是,请记住您可以使用逗号运算符和 ? : 三元运算符和赋值做很多技巧:
#include <stdio.h>
#define FLOATWORK(X) (printf("hello "), printf("world\n"), 0)
#define DOUBLEWORK(X) (X == 5.0 ? printf("It equals 5\n") : \
printf("It doesn't equal 5\n"), 1)
#define F(X) _Generic((X), float: FLOATWORK(X), double: DOUBLEWORK(X))
int main(void) {
F(5.0f);
F(5.0);
}
C 2018 6.5.1.1 定义 _Generic
只接受表达式作为操作数。要将其用于 select 语句,请使用 selection 语句:
switch (_Generic(X, float: 0, double: 1))
{
case 0:
stuff;
break;
case 1:
stuff;
break;
}
这可以根据需要放入宏中。
这导致整个结构成为一个陈述。您的问题并不排除这一点,但是,如果您希望整个构造是一个表达式并且您想要做的“东西”也是表达式,那么您可以使用条件运算符:
_Generic(X, float: 0, double: 1) ? stuff : stuff;
除非您有充分的理由使用类似函数的宏,否则请考虑放弃那些用于普通函数的宏。然后您可以创建 _Generic
宏来创建类型泛型函数 API。示例:
#include <stdio.h>
#include <stdlib.h>
float workf (float x)
{
return x * 2.0f;
}
double worklf (double x)
{
return x * 2.0f;
}
#define work(x) _Generic((x), float: workf, double: worklf)(x)
#define print(x) printf(_Generic((x), float: "%f\n", double: "%lf\n"), (x))
int main (void)
{
float f = 1.0f;
double d = 1.0;
print(work(f));
print(work(d));
print(work(2.0f));
print(work(2.0));
return 0;
}
我需要 select 语句而不是 _Generic()
中的表达式。我知道我可以将它们放在函数中,但我更喜欢保存函数调用并改用宏。我知道另一种可能性是将语句转换为表达式的 GNU 扩展,但如果可能的话我宁愿不使用扩展。
我需要的是这样的:
#define FLOATWORK(X) do{ \
dostuff; \
dostuff; \
dostuff;}while(0)
#define DOUBLEWORK(X) do{ \
dostuff; \
dostuff; \
dostuff;}while(0)
#define GENERICWORK(X) _Generic((X), float: FLOATWORK(X), double: DOUBLEWORK(X))
我想到的另一种可能性是在我的宏中使用逗号运算符,试图将语句转换为带有逗号运算符的表达式。但是,我需要在宏中使用 switch/case
,并且 switch/case
不能是表达式 AFAIK。
那么,总而言之,我能否在不将宏语句放在函数中并且不使用 GCC 表达式语句扩展的情况下实现这一点?
不,你不能,因为它们需要是表达式。但是,请记住您可以使用逗号运算符和 ? : 三元运算符和赋值做很多技巧:
#include <stdio.h>
#define FLOATWORK(X) (printf("hello "), printf("world\n"), 0)
#define DOUBLEWORK(X) (X == 5.0 ? printf("It equals 5\n") : \
printf("It doesn't equal 5\n"), 1)
#define F(X) _Generic((X), float: FLOATWORK(X), double: DOUBLEWORK(X))
int main(void) {
F(5.0f);
F(5.0);
}
C 2018 6.5.1.1 定义 _Generic
只接受表达式作为操作数。要将其用于 select 语句,请使用 selection 语句:
switch (_Generic(X, float: 0, double: 1))
{
case 0:
stuff;
break;
case 1:
stuff;
break;
}
这可以根据需要放入宏中。
这导致整个结构成为一个陈述。您的问题并不排除这一点,但是,如果您希望整个构造是一个表达式并且您想要做的“东西”也是表达式,那么您可以使用条件运算符:
_Generic(X, float: 0, double: 1) ? stuff : stuff;
除非您有充分的理由使用类似函数的宏,否则请考虑放弃那些用于普通函数的宏。然后您可以创建 _Generic
宏来创建类型泛型函数 API。示例:
#include <stdio.h>
#include <stdlib.h>
float workf (float x)
{
return x * 2.0f;
}
double worklf (double x)
{
return x * 2.0f;
}
#define work(x) _Generic((x), float: workf, double: worklf)(x)
#define print(x) printf(_Generic((x), float: "%f\n", double: "%lf\n"), (x))
int main (void)
{
float f = 1.0f;
double d = 1.0;
print(work(f));
print(work(d));
print(work(2.0f));
print(work(2.0));
return 0;
}