我在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
在编译时?
答案 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时,你应该使用你喜欢的任何东西。)