在调整某些给定界面时,我遇到了扩展使用带有大量#defines
的头文件的问题。
我所拥有的是这样的:
#define STATUS_OK 0x00
#define STATUS_FAIL 0x01
#define STATUS_WAIT 0x02
#define STATUS_ILLEGAL 0x03
#define STATUS_FULL 0x04
...
有很多像这样的定义,我很高兴,因为我不必全部写出来。
但是,虽然我可以很好地将它们用于switch
,if
以及其他语句作为0x00
等的替代,但我现在希望有反对方向。< / p>
所以,有了0x00
,我想打印出标识符“STATUS_OK”。
据我所知,这是不可能的,但是什么是一个很好的解决方法,使它成为可能?!是否可以设置这样的数组:
arrayNames[STATUS_OK] = _STATUS_OK_
由STATUS_OK
解析为0x00
而_STATUS_OK_
将解析为“STATUS_OK”?
此外,我正在寻找一种尽可能少使用内存的解决方案。
这是我希望能够做到的:
prinf("%s",resolve(0x00));
-> "STATUS_OK"
我希望,我明确了我要找的东西。
编辑:
感谢所有人,快速而有用的回复!我将使用Larsmans解决方案,并可能尝试将其与qrdl结合使用。可能需要一段时间,我会在完成后替换此编辑。
答案 0 :(得分:3)
您可以使用预处理器的小宏模板和 stringize 运算符来执行此操作。看看:
#include <stdio.h>
#define STATUS_OK 0x05
#define STATUS_BAD 0x09
#define LOOKUP_CASE(x) case x: return #x
const char *lookup_name(int val) {
switch(val) {
LOOKUP_CASE(STATUS_OK);
LOOKUP_CASE(STATUS_BAD);
default: return "<UNDEFINED>";
}
return NULL;
}
int main(void) {
printf("%s\n", lookup_name(STATUS_OK));
printf("%s\n", lookup_name(STATUS_BAD));
return 0;
}
除LOOKUP_CASE
宏外,该示例不言自明。它使用#
运算符生成与其操作数对应的字符串常量,从而避免重复#define
- d常量的名称两次。
这是一个link to ideone这个有效的例子。
答案 1 :(得分:2)
使用X-Macros,但需要更改原始标头文件
答案 2 :(得分:1)
您可以这样做:
const char *status_str(int s)
{
switch(s)
{
case STATUS_OK:
return "STATUS_OK";
/* And so on and so forth */
}
}
答案 3 :(得分:1)
无法从其值中获取标识符的名称。因为在预处理之后标识符不再可用,并且编译器不知道它们。
但是,您可以尝试将其名称存储在数组或类似的其他技巧中。
答案 4 :(得分:1)
一个简单的解决方案是编写两个非常简单的代码生成器。如果将标识符存储在文本文件中,格式为
identifier value
e.g。
STATUS_OK 0x00
STATUS_FAIL 0x01
然后两个简单的Awk脚本可以生成带有#defines
的标头和带有该字符串的C模块。对于标题:
BEGIN {
print("#ifndef _STATUSCODES_H");
print("#define _STATUSCODES_H");
}
{ printf("#define %s %s\n", $1, $2) }
END { print("#endif"); }
对于回到字符串的映射:
BEGIN {
print("#include \"statuscodes.h\"");
print("char const *status_string(int status)");
print("{");
print(" switch (status) {");
}
{ printf(" case %s: \"%s\"\n", $2, $1); }
END {
print(" }");
print("}");
}
然后,当标识符表更改时,让Makefile
生成模块和标题。
答案 5 :(得分:1)
如果没有使用switch
检查每个值或制作包含名称的完整列表,我认为没有针对您的问题的解决方案:
char *s_names[] = {
"STATUS_OK",
"STATUS_FAIL",
...
}
现在您可以通过索引(这是错误代码)简单地访问字符串:
printf("%s", s_names[0x00]); // prints "STATUS_OK"
printf("%s", s_names[STATUS_OK]); // prints "STATUS_OK" too
如果您有值(或宏),这将有效但如果您不想为整个列表浪费太多空间,则可以使用此宏:
#define MACRO_TO_STRING(x) #x
现在您可以将宏转换为字符串,但不能将值转换为字符串:
printf("%s", MACRO_TO_STRING(STATUS_OK)); // prints "STATUS_OK"
printf("%s", MACRO_TO_STRING(0x00)); // but this doesn't work: prints "0x00"