[英]Iterate through enums in C?
假设我有几个在枚举中定义的硬件寄存器:
typedef enum registers
{
REG1 = 0,
REG2 = 1,
REG3 = 2,
REG4 = 4,
REG5 = 6,
REG6 = 8,
REG_MAX,
}
我有这些寄存器的默认值(实际上并没有决定以哪种方式定义它们,#define、array 或 enum...):
// This is just conceptual, not really an enum, array or #define :)
typedef enum values
{
VALUE_REG1 = A,
VALUE_REG2 = B,
VALUE_REG3 = C,
VALUE_REG4 = 53,
VALUE_REG5 = 88,
VALUE_REG6 = 24,
MAX_NUM_REG_VALUES
}
我有一个可以读取硬件寄存器的函数:
uint8 readRegs(uint8 regaddr);
现在我想遍历registers
,并在每个元素上调用readRegs()
函数并将其与枚举regvalues
进行比较。 看起来像:
registers regs;
reg_values values;
uint8 readfromregs;
for (regs = REG1; regs <= REG_MAX; regs++)
{
readfromregs = readRegs(regs);
for (values = VALUE_REG1; reg_values <= MAX_NUM_REG_VALUES; reg_values++)
{
if (readfromregs != values)
{
// Value not correct
}
else
{
// value correct
}
}
}
这将不起作用,因为不可能以这种方式在枚举中迭代。 有人有更好的解决方案吗? 如何定义构造enum reg_values
? 枚举寄存器必须是固定的(这不能是对数组的更改)。
我可能会定义一个结构
struct RegInfo
{
registers number;
values defaultValue;
}
然后我将创建一个将寄存器编号与默认值匹配的数组
struct RegInfo registerInfo[] =
{
{ REG1, VALUE_REG1 },
{ REG2, VALUE_REG2 },
{ REG3, VALUE_REG3 },
{ REG4, VALUE_REG4 },
{ REG5, VALUE_REG5 },
{ REG6, VALUE_REG6 },
};
现在迭代寄存器:
for (int i = 0 ; i < sizeof registerInfo / sizeof(RegInfo) ; ++i)
{
values value = readFromReg( registerInfo[i].number);
if (value != registerInfo[i].defaultValue)
{
// Not the default
}
}
如果你想要一个内部循环来对抗每个值,除了数组可以直接是值之外的相同技巧
values allValues[] = { VALUE_REG1, Value_REG2, ... , VALUE_REG6 };
您可能会忘记将新值/寄存器放入相关数组中,但这就是单元测试的目的。
REG_MAX
将是9
, MAX_NUM_REG_VALUES
将是25
所以你不能使用它们。 您必须以不同的方式枚举常量。
根据@JeremyP 的另一个答案中的 struct 解决方案,您可以将第三个枚举用于实际索引:
typedef enum
{
REG_INDEX1 = REG1,
REG_INDEX2 = REG2,
REG_INDEX3 = REG3,
REG_INDEX4 = REG4,
REG_INDEX5 = REG5,
REG_INDEX6 = REG6,
REG_INDEX_N // number of registers
} reg_index;
这提供了一些提高数据完整性的方法:
struct RegInfo registerInfo[] =
{
[REG_INDEX1] = { REG1, VALUE_REG1 },
[REG_INDEX2] = { REG2, VALUE_REG2 },
[REG_INDEX3] = { REG3, VALUE_REG3 },
[REG_INDEX4] = { REG4, VALUE_REG4 },
[REG_INDEX5] = { REG5, VALUE_REG5 },
[REG_INDEX6] = { REG6, VALUE_REG6 },
};
_Static_assert(sizeof(registerInfo)/sizeof(*registerInfo) == REG_INDEX_N,
"Enum not in sync with array initializer");
这是我推荐的解决方案。
如果您对数据完整性非常迂腐并希望避免代码重复,那么您还可以使用一些邪恶的宏魔法。 即以严重降低可读性为代价的“X 宏”:
// whatever A, B and C is supposed to be
#define A 10
#define B 11
#define C 12
#define REG_LIST \
X(0, A) \
X(1, B) \
X(2, C) \
X(4, 53) \
X(6, 88) \
X(8, 24) \
int main (void)
{
// iterate through the value pairs:
#define X(reg, val) printf("reg: %d val:%.2d\n", reg, val);
REG_LIST
#undef X
}
同样,您可以使用 X 宏来创建枚举:
typedef enum // create REG1, REG2, REG4 etc
{
#define X(key, val) REG##key = key,
REG_LIST
#undef X
} registers;
typedef enum // create VALUE_REG1, VALUE_REG2, VALUE_REG4 etc
{
#define X(key, val) VALUE_REG##key = val,
REG_LIST
#undef X
} values;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.