将字符串展开为关键字

时间:2016-03-25 23:18:03

标签: c macros c-preprocessor

我正在编写一个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。所有这些都可以在编译时根据我的程序的需要进行评估 我想要做的是保持任何类型的对象,因此使用enum或检查字符串相等将不起作用。

1 个答案:

答案 0 :(得分:1)

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

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

  1. 能够在代码中的某处定义struct void *的“{1}}
  2. 能够从struct的名称
  3. 访问该类型的关键字

    那么你很可能会以typeof结束。它是一个GNU extension,所以它只适用于GCC,但它可以工作。

    在此处的示例代码中,您使用MYSTRUCT宏定义某个“类型”的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的“类型”以确定printf()的格式代码,但未解决此问题。

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

    需要它)