将字符串扩展为关键字
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
或检查字符串相等性将不起作用。
简答:不可能。不是你的方式。宏可以生成标记(关键字,如果你愿意的话),但不能将字符串转换为它们。
也就是说,如果你追求的东西真的是
- 能够在代码中的某处定义一个
struct
及其 void *
的 "type",
- 能够通过
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
需要它)
我正在编写一个 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
或检查字符串相等性将不起作用。
简答:不可能。不是你的方式。宏可以生成标记(关键字,如果你愿意的话),但不能将字符串转换为它们。
也就是说,如果你追求的东西真的是
- 能够在代码中的某处定义一个
struct
及其void *
的 "type", - 能够通过
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
需要它)