_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;
}