枚举中的元素数量

问题描述 投票:0回答:9

在 C 中,有没有一种很好的方法来跟踪枚举中的元素数量?我见过

enum blah {
    FIRST,
    SECOND,
    THIRD,
    LAST
};

但这仅在项目是连续的且从零开始时才有效。

c enums
9个回答
84
投票

如果您不分配枚举,您可以执行以下操作:

enum MyType {
  Type1,
  Type2,
  Type3,
  NumberOfTypes
}

NumberOfTypes 将计算为 3,这是实际类型的数量。


45
投票

我不相信有。但是,如果这样的数字不是连续的,并且您还没有在某处拥有它们的列表,您会如何处理它们呢?如果它们是连续的但以不同的数字开始,您始终可以这样做:

enum blah {
    FIRST = 128,
    SECOND,
    THIRD,
    END
};
const int blah_count = END - FIRST;

34
投票

老问题,我知道。这是为有同样问题的谷歌用户准备的。

您可以使用X-宏

示例:

//The values are defined via a map which calls a given macro which is defined later
#define ENUM_MAP(X) \
      X(VALA, 0)    \
      X(VALB, 10)   \
      X(VALC, 20)

//Using the map for the enum decl
#define X(n, v) [n] = v,
typedef enum val_list {
    ENUM_MAP(X) //results in [VALA] = 0, etc...
} val_list;
#undef X

//For the count of values
#define X(n, v) + 1
int val_list_count = 0 + ENUM_MAP(X); //evaluates to 0 + 1 + 1 + 1
#undef X

这对于 IDE 来说也是透明的,因此自动完成功能可以正常工作(因为所有操作都在预处理器中完成)。


13
投票

不幸的是,没有。没有。


6
投票

我知道这是一个非常古老的问题,但由于接受的答案是错误的,我觉得有必要发布自己的答案。我将重用已接受的答案的示例,稍作修改。 (假设枚举是连续的。)

// Incorrect code, do not use!
enum blah {
  FIRST   =  0,
  SECOND, // 1
  THIRD,  // 2
  END     // 3
};
const int blah_count = END - FIRST;
// And this above would be 3 - 0 = 3, although there actually are 4 items.

任何开发者都知道原因:

count = last - first + 1
。 这适用于任何符号组合(两端都是负数,都是正数,或者只有一端是负数)。你可以试试。

// Now, the correct version.
enum blah {
  FIRST   =  0,
  SECOND, // 1
  THIRD,  // 2
  END     // 3
};
const int blah_count = END - FIRST + 1; // 4

编辑:再读一遍文字,我有一个疑问。

END
是否意味着不属于所提供物品的一部分?这对我来说看起来很奇怪,但好吧,我想这可能是有道理的......


3
投票

嗯,由于枚举无法在运行时更改,因此您可以做的最好的事情是:

enum blah {
    FIRST = 7,
    SECOND = 15,
    THIRD = 9,
    LAST = 12
};
#define blahcount 4 /* counted manually, keep these in sync */

但我发现很难想象这些信息会派上用场的情况。你到底想做什么?


3
投票
int enaumVals[] =
{
FIRST,
SECOND,
THIRD,
LAST
};

#define NUM_ENUMS sizeof(enaumVals) / sizeof ( int );

1
投票
#include <stdio.h>

// M_CONC and M_CONC_ come from https://stackoverflow.com/a/14804003/7067195
#define M_CONC(A, B) M_CONC_(A, B)
#define M_CONC_(A, B) A##B

#define enum_count_suffix _count
#define count(tag) M_CONC(tag, enum_count_suffix)
#define countable_enum(tag, ...) \
  enum tag {__VA_ARGS__}; \
  const size_t count(tag) = sizeof((int []) {__VA_ARGS__}) / sizeof(int)

// The following declares an enum with tag `color` and 3 constants: `red`,
// `green`, and `blue`.
countable_enum(color, red, green, blue);

int main(int argc, char **argv) {
  // The following prints 3, as expected.
  printf("number of elements in enum: %d\n", count(color));
}

0
投票

嗯,这已经很老了,但是我找到了这里没有提到的方法。

大多数编译器都提供了

__COUNTER__
宏。该宏最初扩展为 0,每当使用它时,它都会给自身加 1。它在目标文件的开头重置。这意味着你可以这样写:

#include <stdio.h>

const int TestSizeInitial = __COUNTER__;
typedef enum {
    TEST_0 = __COUNTER__,
    TEST_1 = __COUNTER__,
    TEST_2 = __COUNTER__
} Test;
const int TestSize = __COUNTER__ - TestSizeInitial - 1;

const int TestSizeInitial2 = __COUNTER__;
typedef enum {
    TEST2_0 = __COUNTER__,
    TEST2_1 = __COUNTER__,
    TEST2_2 = __COUNTER__,
    TEST2_3 = __COUNTER__
} Test2;
const int TestSize2 = __COUNTER__ - TestSizeInitial2 - 1;

int main()
{
    printf("Number of Test variants = %i\n", TestSize);
    printf("Number of Test2 variants = %i\n", TestSize2);
    
    printf("TEST_0 = %i\n", TEST_0);
    printf("TEST_1 = %i\n", TEST_1);
    printf("TEST_2 = %i\n", TEST_2);
    
    printf("TEST2_0 = %i\n", TEST2_0);
    printf("TEST2_1 = %i\n", TEST2_1);
    printf("TEST2_2 = %i\n", TEST2_2);
    printf("TEST2_3 = %i\n", TEST2_3);

    return 0;
}

这将打印:

Number of Test variants = 3
Number of Test2 variants = 4
TEST_0 = 1
TEST_1 = 2
TEST_2 = 3
TEST2_0 = 6
TEST2_1 = 7
TEST2_2 = 8
TEST2_3 = 9

这样做的优点是不使用最后一个变体作为计数器,这可能会弄乱 switch 语句。缺点是,正如您所看到的,它使得很难推断枚举变体的实际值。只要您不需要它们的明确值,就可以了。例如,如果将

Test
放入
test.h
中,并将
Test2
放入
test2.h
中,则调用 include 语句的顺序会更改枚举变体的值。它不会更改
TestSize
TestSize2
的值,因为它们是根据与
__COUNTER__
初始值的差来定义的。

© www.soinside.com 2019 - 2024. All rights reserved.