In C how to loop for each enumerated literal where the literals do't have consecutive values

狂风中的少年 提交于 2019-12-08 06:03:48

问题


Suppose i have the following enumerated literal

enum
{
valueA = 5,
valueB = 7,
valueC = 9,
valueD = 14,
valueE = 15
}myEnumType; 

and i want to loop through each literal eg

for (enumType myValEnum = valueA; myValEnum <= valueE; myValEnum++)
{
    MyFunction(mValEnum);
}

will that work or will I end up calling MyFunction with values 5,6,7,8,9,10,11,12,13,14,15 ?


回答1:


You can't do that, there's no support for a "foreach" type of iteration over the enumeration in C. Basically, enumerations are just aliased integers, with little extra support.

You need to use a mapping table, that allows you to map consecutive indices to values of the enumerated type:

static const myEnumType myEnumMap[] = { valueA, valueB, valueC, valueD, valueE};

then you can use a plain loop over that array:

for(size_t i = 0; i < sizeof myEnumMap / sizeof *myEnumMap; ++i)
{
  const myEnumType ie = myEnumMap[i];
  /* process ie */
}

Note that the type of myEnumMap is the type of your enumeration, it's not a plain "array of integers".

This has the downside of requiring the enum to be enumerated twice (once in its own definition, then again in the myEnumMap initializer). It's possible to work around that using macro trickery (such as X macros), but there's no real convenient/easy way to do it.




回答2:


Directly it is not possible to loop through each enum literal. You can do that indirectly by using an array of integers. Assign each enum literals to array elements sequentially and then you can loop through each array element.




回答3:


I am not sure, if this is helpful, but I had the following thoughts:

We have to save the possible values of the enum somewhere, because this information doesn't exist in memory, so we need something like an array with the possible values:

enum {
    valueA = 5,
    valueB = 7,
    valueC = 9,
    valueD = 14,
    valueE = 15
} myEnumType;

const int myEnumTypeArr[] = { 5, 7, 9, 14, 15 };

where it's possible to not store that array but to create a temporary object whenever needed (e.g. we could wrap the array contents into a macro).

I don't think that's a good solution, though, because if you change your enum, you must change the array. If you forget to do so, the compiler won't warn you and it may result in hard-to-find bugs.

So maybe the following is helpful: You use the array for the values and the enum constants as indexes:

enum { valueA, valueB, valueC, dummy } myEnumType; // dummy must stay at last position
const int myEnumTypeArr[] = { 5, 7, 9 };

so you use myEnumTypeArr[valueA] rather than valueA directly (with the drawback, that it's no longer a constant, e.g. can't be used as a case label) and maybe something like that (somewhat ugly, though)

static_assert( sizeof myEnumTypeArr / sizeof *myEnumTypeArr == dummy );

to prevent the aforementioned bug.

HTH




回答4:


You can't do it using enum and loops. Your loop

for (enumType myValEnum = valueA; myValEnum <= valueE; myValEnum++)
{
    MyFunction(mValEnum);
}

iterates from 5 to 15(5,6,7,8,9,10,11,12,13,14,15). According to my knowledge pointer to enum's also can't help you here.



来源:https://stackoverflow.com/questions/20993142/in-c-how-to-loop-for-each-enumerated-literal-where-the-literals-dot-have-consec

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!