c - 使用预处理器##动态调用函数

标签 c

我有一个名为create_car的函数。我正在尝试使用预处理器宏,以便可以通过执行 Create(car) 来调用该函数。这是我迄今为止所拥有的:

#define ObjName(X)  _Generic((X), struct Person: "person", struct Car: "car")
#define NewObj(X)   create_ ## ObjName(X)

struct Car* create_car(void) 
{
   // do something here
}
struct Car {
    char* make;
    char* model;
    int year;
    void (*print)(struct Car*);
};

int main(void)
{
    struct Car *car = NewObj(struct Car);
}

但是在尝试时出现以下错误:

gen.c:5:21: warning: implicit declaration of function ‘create_ObjName’; did you mean ‘create_car’? [-Wimplicit-function-declaration]
 #define NewObj(X)   create_ ## ObjName(X)
                     ^
gen.c:40:5: note: in expansion of macro ‘NewObj’
     NewObj(struct Car);
     ^~~~~~
gen.c:40:12: error: expected expression before ‘struct’
     NewObj(struct Car);
            ^
gen.c:5:40: note: in definition of macro ‘NewObj’
 #define NewObj(X)   create_ ## ObjName(X)

我如何尝试从宏创建对象时,上面出现的问题是什么?

我正在寻找预处理/编译后的代码:

int main(void)
{
    struct Car *car = create_car();
}

最佳答案

你不能这样做。 C 预处理器不知道 _Generic。它将视为一个普通名称,一个进一步扩展的潜在候选名称。

但是,您可以在 NewObj 宏的定义中使用_Generic。 问题是 NewObj(X) 的参数不是值而是类型。 但是,您可以通过将 NULL 指针分派(dispatch)到 X 来绕过它 找到合适的构造函数。

#define NewObj(X)  _Generic(((X*)0), struct Person*: create_person(), struct Car*: create_car())

简化的结果代码是:

#include <stdio.h>

struct Car;
struct Person;

struct Car* create_car(void) {
    puts("Create a car");
    return NULL;
}

struct Person* create_person(void) {
    puts("Create a person");
    return NULL;
}

#define NewObj(X)  _Generic(((X*)0), struct Person*: create_person(), struct Car*: create_car())

int main(void)
{
    struct Car *car = NewObj(struct Car);
    struct Person *person = NewObj(struct Person);
    return 0;
}

按预期打印:

Create a car
Create a person

无论如何,我建议直接调用create_car()/create_person(),因为它更具可读性。

关于c - 使用预处理器##动态调用函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66450490/

相关文章:

c - 在不写入文件描述的情况下使 select() 破解?

c - 在递归函数中打印函数参数

clock_t 除法结果为 0

c - 有没有办法到管道的最后位置而不是读取直到什么都没有?

C - 将 "h_addr_list"数组转换为类型 "struct in_addr **"

将计算字符串转换为 uint32_t,而不将其复制到 c 中的 char[] 缓冲区中

c - GNU cpp 是否奇怪地为零参数的宏解释 C99 标准?

java - 套接字编程,C-java

c - 是否有可能找出 strcpy 的当前语法何时添加到 C 标准中?

c - 如何通过引用传递结构并更改其值