基于枚举的静态数组:C头

时间:2013-09-05 19:21:33

标签: c

我在C头文件中有一个枚举值。我想定义一个额外的数组或一组值,其中每个值对应一个枚举值。本质上,该数组将是与每个枚举值相关的一些信息的查找表。但是,我想在编译时在头文件中执行此操作。

实现这一目标的好方法是什么?

以下是如何使用两个单独的枚举或定义结构来完成它的示例。有没有更优雅的方法来完成这个只使用op枚举?

enum op {
op1,
op2,
op3
};

enum op_information {
op1_info = 0xff,
op2_info = 0xf3,
op3_info = 0xc1
}

更新:如果有任何方法使用引用静态定义数组,对我来说同样有价值的帮助会回答。也就是说,而不是:

ushort op_information = { 0xff, 0xf3, 0xc1 },

我们可以完成

ushort op_information[3]
op_information[op.op1] = 0xff;
op_information[op.op2] = 0xf3;
op_information[op.op3] = 0xc1

在编译时?

4 个答案:

答案 0 :(得分:5)

使用C99 指定的初始化程序

ushort op_information[] = {
    [op1] = 0xff,
    [op2] = 0xf3,
    [op3] = 0xc1,
};

答案 1 :(得分:1)

您可以使用旧的GNU cpp技巧。创建一个完全由宏调用组成的包含文件。

/* opdefs.h */
OP(op1, 0xff)
OP(op2, 0xff)

现在通过使用以下之间的include重复定义和取消定义OP来构建必要的枚举:

#define OP(Id, Val) Id,
enum op {
#include "opdefs.h"
};
#undef OP

// Handy for debugging, e.g. printf("%s", op_to_string[the_op]);
#define OP(Id, VaL) #I,
char op_to_string[] = {
#include "opdefs.h"
};
#undef OP

#define OP(Id, Val) Id ## _info = Val,
enum op_information {
#include "opdefs.h"
};
#undef OP

我相信你会发现同样的包含也会让你生成你想要的数组。

<强>加成

正如@Sebastian建议的那样,你可以用另一个宏替换包含文件:

#define OP_DEFS \
OP(op1, 0xff) \
OP(op2, 0xff)

#define OP(Id, Val) Id,
enum op { OP_DEFS };
#undef OP

#define OP(Id, VaL) #I,
char op_to_string[] = { OP_DEFS };
#undef OP

#define OP(Id, Val) Id ## _info = Val,
enum op_information { OP_DEFS };
#undef OP

一般来说,如果有很多OP defs,或者你需要从多个来源使用它们,那么include文件方法会更清晰。对于一个文件中的短列表,宏方法更清晰。

答案 2 :(得分:0)

如果你需要将结果作为编译时常量,你可以只做一个嵌套的三元表达式

#define INFO(X) ( (X) == op1 ? val1 : ((X) == op2 ? val2 : .... ) )

请注意,这会多次评估X,所以如果X有副作用,那就搞砸了。

但是如果X是一个编译时整数表达式,那么任何C编译器都必须评估这个编译时间。

使用新的C标准,C11,_Generic功能,甚至可以找出是否是编译时表达式,如果不是,则通过函数调用替换三元表达式避免评估问题。

答案 3 :(得分:0)

无论你做什么,你都可能想要进行自我测试。使用断言进行自检,因此您只能在调试版本中进行测试。

enum op {
    op1,
    op2,
    op3,
};

enum op_information {
    op1_info = 0xff,
    op2_info = 0xf3,
    op3_info = 0xc1,
};

ushort op_information = { op1_info, op2_info, op3_info };

// then somewhere, e.g. in a function called _OnBootup():
assert(op1_info == op_information[op1]);
assert(op2_info == op_information[op2]);
assert(op3_info == op_information[op3]);

另外,对于如上所述的真正无聊和真正数据驱动的东西,我通常会编写一个编写适当C代码的Python程序。你真的不需要为真正固定的东西做这件事,比如当你为一个冷冻的标准编解码器编写解码器时;但是如果枚举和匹配值不断变化(如在R&amp; D期间)并且可能容易出错以使所有内容保持最新,只需将op名称和值放在Python字典中并让Python代码生成所有样板C代码。 (显然,当我使用Python时,你应该使用你喜欢的任何东西。)