Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/oracle/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 有一个#定义值替换的列表,如何将值解析为标识符字符串?_C_C Preprocessor - Fatal编程技术网

C 有一个#定义值替换的列表,如何将值解析为标识符字符串?

C 有一个#定义值替换的列表,如何将值解析为标识符字符串?,c,c-preprocessor,C,C Preprocessor,在修改某些给定的接口时,我遇到了使用大量的#定义扩展头文件的问题 我拥有的是这样的东西: #define STATUS_OK 0x00 #define STATUS_FAIL 0x01 #define STATUS_WAIT 0x02 #define STATUS_ILLEGAL 0x03 #define STATUS_FULL 0x04 ... arrayNames[STATUS_OK] = _STATUS_OK_ const char *status_str(

在修改某些给定的接口时,我遇到了使用大量的
#定义扩展头文件的问题

我拥有的是这样的东西:

#define STATUS_OK      0x00
#define STATUS_FAIL    0x01
#define STATUS_WAIT    0x02
#define STATUS_ILLEGAL 0x03
#define STATUS_FULL    0x04
...
arrayNames[STATUS_OK] = _STATUS_OK_
const char *status_str(int s)
{
    switch(s)
    {
        case STATUS_OK:
            return "STATUS_OK";
        /* And so on and so forth */
    }
}
有很多这样的定义,我对此很高兴,因为我不必全部写出来

然而,虽然我可以很好地将它们用于
switch
if
和其他语句,以替代
0x00
等等,但我现在希望使用相反的方向

因此,有了
0x00
,我想打印出标识符“STATUS\u OK”

据我所知,这是不可能的,但有什么好的解决办法使之成为可能呢?!可以这样设置阵列吗:

#define STATUS_OK      0x00
#define STATUS_FAIL    0x01
#define STATUS_WAIT    0x02
#define STATUS_ILLEGAL 0x03
#define STATUS_FULL    0x04
...
arrayNames[STATUS_OK] = _STATUS_OK_
const char *status_str(int s)
{
    switch(s)
    {
        case STATUS_OK:
            return "STATUS_OK";
        /* And so on and so forth */
    }
}
其中
状态\u正常
将解析为
0x00
状态\u正常
将解析为“状态\u正常”

此外,我正在寻找一个解决方案,它使用尽可能少的内存,尽可能做到这一点

这就是我希望能够做到的:

prinf("%s",resolve(0x00));
-> "STATUS_OK"
我希望,我清楚地表明了我在寻找什么

编辑:


感谢大家的支持,快速而有用的回复!我将使用Larsmans的解决方案,并尝试将其与qrdl中的一个结合起来。可能需要一段时间,完成后我将替换此编辑。

您可以执行以下操作:

#define STATUS_OK      0x00
#define STATUS_FAIL    0x01
#define STATUS_WAIT    0x02
#define STATUS_ILLEGAL 0x03
#define STATUS_FULL    0x04
...
arrayNames[STATUS_OK] = _STATUS_OK_
const char *status_str(int s)
{
    switch(s)
    {
        case STATUS_OK:
            return "STATUS_OK";
        /* And so on and so forth */
    }
}

无法从其值中获取标识符的名称。因为在预处理之后标识符不再可用,并且编译器不知道它们


但是,您可以尝试将它们的名称存储在数组中或其他类似的技巧。

一个简单的解决方案是编写两个非常简单的代码生成器。如果您以简单格式将标识符存储在文本文件中

identifier value
e、 g

然后,两个简单的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
在标识符表更改时生成模块和标题。

使用,尽管它需要更改您的原始标题文件

如果不使用
开关
检查每个值或制作包含名称的完整列表,我认为没有解决问题的方法:

char *s_names[] = {
    "STATUS_OK",
    "STATUS_FAIL",
    ...
}
现在,您只需通过索引(即错误代码)访问字符串即可:

如果您有该值(或宏),这将起作用,但如果您不想为整个列表浪费太多空间,则可以使用此宏:

#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"

您可以使用一些宏向导和预处理器的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;
}
#包括
#定义状态\u OK 0x05
#定义状态_BAD 0x09
#定义查找_案例(x)案例x:返回#x
常量字符*查找名称(int val){
开关(val){
查找案例(状态正常);
查找案例(状态错误);
默认值:返回“”;
}
返回NULL;
}
内部主(空){
printf(“%s\n”,查找名称(状态确定));
printf(“%s\n”,查找名称(状态错误));
返回0;
}
除了
LOOKUP\u案例
宏之外,该示例是不言自明的。它使用
#
运算符生成与其操作数对应的字符串常量,从而避免重复
#define
-d常量的名称两次


下面是这个工作示例的示例。

这是我目前正在做的事情-虽然不是在这样一个整洁的函数中。然而,我对此并不太高兴,因为我有点偏执,当我想到“什么可以改变?”的时候,从好的方面来说,我可以把这个和rountines结合起来处理地位的变化。现在这看起来很有趣!我将拥有所有的字符串,并且可以在某些事情发生变化时自动重新生成它们,而且我不必使用任何函数来解析它们-很好!我也这么认为,谢谢你让我放心。关于C的很多细节我还是有点犹豫。也很好,谢谢分享!甚至可以将您的尝试与Larsmans结合起来,以获得一个非常好的转换例程。(此外,您可以使用相同的方法生成一个开关,尽管这对可读性没有多大帮助)谢谢,但您的阵列解决方案的主要缺点是固定排列-如果OK为
0x00
,而失败为
0xFF
?您的第二个解决方案看起来更有希望,但是,我认为dasblinkenlight将这一尝试提升到了一个新的层次。我认为每个宏的值都比前一个多一个。好吧,我认为这是误导。在没有编号跳转的情况下,这很有用。此外,我还发现了另一种情况,这个
MACRO_TO_STRING(x)#x
非常漂亮!谢谢现在,对于Larsman/qrdl的解决方案,这将是一个艰难的决定。不幸的是,它将不得不等到明天-现在就到此为止。如果有人能对给定的解决方案添加一些比较分析,我将不胜感激。