Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/66.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 - Fatal编程技术网

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

基于枚举的静态数组:C头,c,C,我有一个C头文件中的值枚举。我想定义一个附加数组或一组值,其中每个值对应一个枚举值。从本质上讲,数组将是一个查找表,用于查找与每个枚举值相关的一些信息。但是,我希望在编译时在头文件中执行此操作 实现这一目标的好方法是什么 下面是一个如何使用两个单独的枚举或定义结构来实现它的示例。是否有更优雅的方法仅使用op枚举来实现这一点 enum op { op1, op2, op3 }; enum op_information { op1_info = 0xff, op2_info = 0xf3, op3

我有一个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
编译时?

使用C99指定的初始值设定项:


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

#define INFO(X) ( (X) == op1 ? val1 : ((X) == op2 ? val2 : .... ) )
请注意,这会对
X
进行多次计算,因此如果
X
有副作用,您就完蛋了

但是,如果
X
是编译时整数表达式,任何C编译器也必须在编译时对其求值


有了新的C标准C11,
\u Generic
特性,甚至有办法确定这是否是一个编译时表达式,如果不是,用一个避免求值问题的函数调用替换三元表达式。

无论您做什么,您都可能需要进行自检。对自检使用断言,以便只在调试生成中进行测试

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时,您应该使用您喜欢的任何东西。)

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

/* opdefs.h */
OP(op1, 0xff)
OP(op2, 0xff)
现在,通过使用include-between重复定义和取消定义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
我相信您会看到,相同的include也将允许您生成所需的数组

添加

正如@Sebastian所建议的,您可以用另一个宏替换include文件:

#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-def,或者需要从多个源使用它们,那么include-file方法更干净。宏方法只对一个文件中的短列表更干净。

这正是我想要的。不幸的是,看起来这个特性不再被C++支持了?这个头文件将不幸地应用于C、C++和C语言应用程序中。@ TSM:你将用C语言应用程序共享一个C头文件?@ TSM:指定的初始化器根本不在C++中(它们只添加到C,C和C++是单独的标准语言)。您可以通过在链接到所有项目(例如作为库)的C文件中定义这些常量来解决这个问题。然后,您的头只需要说
extern ushort op_information[]
。您不需要包含文件#定义OPDEFS(OP)OP(op1,0xff)OP(op2,0xff)也可以工作(你可以用反斜杠将它拆分成单独的行)。@Sebastian。我总是有很长的定义列表,因此发现include更干净,但是对于短列表,您的方法更好。我将编辑答案。
#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