3

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

有什么好方法可以做到这一点?

这是一个如何使用两个单独的枚举或定义结构来完成它的示例。有没有更优雅的方法来仅使用操作枚举来完成此操作?

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

4 回答 4

7

使用 C99指定的初始化器

ushort op_information[] = {
    [op1] = 0xff,
    [op2] = 0xf3,
    [op3] = 0xc1,
};
于 2013-09-05T19:28:57.997 回答
1

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

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

现在通过重复定义和取消定义 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 或者您需要从多个来源使用它们,则包含文件方法会更干净。宏方法仅对一个文件中的短列表更清晰。

于 2013-09-05T19:49:43.723 回答
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]);

另外,对于像上面这样非常无聊和真正数据驱动的东西,我通常会编写一个 Python 程序来编写适当的 C 代码。对于真正固定的事情,您并不需要这样做,例如为冻结的标准编解码器编写解码器时;但是如果枚举和匹配值不断变化(如在研发过程中),并且保持一切都是最新的可能容易出错,只需将操作名称和值放在 Python 字典中并让 Python 代码生成所有样板 C代码。(很明显,当我使用 Python 时,你应该使用你喜欢的任何东西。)

于 2013-09-05T19:49:23.690 回答
0

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

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

请注意,这会评估X多次,所以如果X有副作用,你就完蛋了。

但是 ifX是一个编译时整数表达式,任何 C 编译器也必须评估这个编译时间。

使用新的 C 标准 C11_Generic功能,甚至可以确定这是否是编译时表达式,如果不是,则用函数调用替换三元表达式,从而避免评估问题。

于 2013-09-05T19:38:12.353 回答