首页 > 解决方案 > 将联合作为宏中的两个参数之一传递

问题描述

我正在尝试定义一个通用/宏函数来设置我定义的联合的属性。我以前使用过宏,但从未尝试过传递多个参数。在这种情况下,我得到了一个代表一个变量的联合(没什么有趣的),我想要一个单独的集合函数,允许我在不指定数据类型的情况下设置联合实例的正确属性。这是我的代码:

// represents a variable
union Var {
  float f;
  char *s;
  bool b;
  // 'f' 's' or 'b'
  char type;
};

// setter
void set_int(union Var *var, int newval) { var->f = (float)newval; var->type = 'f'; }
void set_float(union Var *var, float newval) { var->f = newval; var->type = 'f'; }
void set_char(union Var *var, char newval) { var->s = (char[2]){newval, 0}; var->type = 's'; }
void set_string(union Var *var, char *newval) { var->s = newval; var->type = 's'; }
void set_bool(union Var *var, bool newval) { var->b = newval; var->type = 'b'; }
#define set(VAR, X) \
  _Generic((X), \
    int: set_int(union Var, X), \
    float: set_float(union Var), \
    char: set_char(union Var), \
    char *: set_string(union Var), \
    bool: set_bool(union Var))(X)

int main(void) {
    union Var myvar;

    // myvar.f = 1.5; myvar.type = 'f'; works, but i want to do this instead:
    set(&myvar, 1.5);

    return 0;
}

我得到的输出:

var.c: In function ‘main’:
var.c:92:18: error: expected expression before ‘union’
     int: set_int(union Var, X), \
                  ^~~~~
var.c:117:5: note: in expansion of macro ‘set’
     set(&myvar, 1.5);
     ^~~
var.c:92:10: error: too few arguments to function ‘set_int’
     int: set_int(union Var, X), \
          ^~~~~~~
var.c:117:5: note: in expansion of macro ‘set’
     set(&myvar, 1.5);
     ^~~
var.c:85:6: note: declared here
 void set_int(union Var *var, int newval) { var->f = newval; var->type = 'f'; }
      ^~~~~~~

我越来越绝望,所以任何帮助将不胜感激!

PS:我一点儿也不擅长C,所以如果我犯了一个愚蠢的错误,请不要让我失望。:)

标签: c

解决方案


您的宏正在扩展以将第一个参数的类型名称传递给函数,这是无效的语法。您希望传递任何VAR参数:

#define set(VAR, X) \
  _Generic((X), \
    int: set_int, \
    float: set_float, \
    double: set_float, \
    char: set_char, \
    char *: set_string, \
    bool: set_bool)((VAR), (X))

推荐阅读