将字符串扩展为关键字

Expand string into keyword

我正在编写一个 struct 程序,需要存储有关它所持有的类型的信息。数据在结构内部表示为指向 void 的指针。我的意思的一个简短例子:

#include <stdio.h>

struct foo {
    void *data;
    char *type;
};

int main() {
    struct foo bar = {{'a', 'b', 'c'}, "char"};
    printf("%s\n", (STRING_TO_TYPE(bar.type))bar.data);
    return 0;
}

我需要一个 STRING_TO_TYPE 宏的实现,它将 "char" 替换为 char。所有这些都可以在编译时评估我程序的需要。
我想要做的是保存一个 any 类型的对象,因此使用 enum 或检查字符串相等性将不起作用。

简答:不可能。不是你的方式。宏可以生成标记(关键字,如果你愿意的话),但不能将字符串转换为它们。

也就是说,如果你追求的东西真的是

  1. 能够在代码中的某处定义一个 struct 及其 void * 的 "type",
  2. 能够通过 struct 的名称访问该类型作为关键字,

那么你很可能会得到 typeof。它是 GNU extension,因此它只能在 GCC 中工作,但它确实有效。

在此处的示例代码中,您使用 MYSTRUCT 宏定义某个 "type" 的 struct,并使用 TYPE 宏获取类型。 __COUNTER__ predefined macro 防止类型重新定义(每个 struct 都是它自己的类型,请参阅 gcc -E)并且 MYSTRUCT 的三个宏级别用于对其进行适当的字符串化。

#include <stdio.h>

#define TYPE(x) typeof(x.type)

#define MYSTRUCT(name, type) MYSTRUCT_INTER(name, type, __COUNTER__)

#define MYSTRUCT_INTER(name, type, counter) MYSTRUCT_RAW(name, type, counter)

#define MYSTRUCT_RAW(xName, xType, xCounter) \
    struct mystruct_## xCounter { \
        void * data; \
        xType type; \
    } xName

int main(void) {
    MYSTRUCT(foo, int);
    foo.data = (void *)42;

    TYPE(foo) tmp = foo.data;    /* <-- Here, tmp is an int */
    printf("%d\n", tmp);

    MYSTRUCT(bar, int*);
    bar.data = &tmp;

    TYPE(bar) tmp2 = bar.data;    /* <-- Here, tmp2 is an int* */
    printf("%p\n", tmp2);

    MYSTRUCT(baz, char*);
    baz.data = "Hello world";
    printf("%s\n", (TYPE(baz))baz.data);
    /* ^Expands to (char *)   baz.data */
}

请注意,我仍然需要知道 struct 的 "type" 才能确定 printf() 的格式代码,但没有要求解决这个问题。

不要忘记使用 -std=gnu** 进行编译(typeof 需要它)