Количество элементов в перечислении - PullRequest
39 голосов
/ 03 апреля 2009

В C есть хороший способ отследить количество элементов в перечислении? Я видел

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

Но это работает, только если элементы являются последовательными и начинаются с нуля.

Ответы [ 9 ]

65 голосов
/ 18 июня 2012

Если вы не присваиваете свои перечисления, вы можете сделать что-то вроде этого:

enum MyType {
  Type1,
  Type2,
  Type3,
  NumberOfTypes
}

NumberOfTypes оценивается как 3, что является числом реальных типов.

35 голосов
/ 03 апреля 2009

Я не верю, что есть. Но что бы вы сделали с таким числом, если оно не является последовательным, и у вас еще нет списка их где-нибудь? И если они последовательные, но начинаются с другого номера, вы всегда можете сделать:

enum blah {
    FIRST = 128,
    SECOND,
    THIRD,
    END
};
const int blah_count = END - FIRST;
20 голосов
/ 18 августа 2014

Старый вопрос, я знаю. Это для гуглеров с таким же вопросом.

Вы можете использовать X-Macros

Пример:

//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, поэтому автозаполнение будет работать нормально (как все это делается в препроцессоре).

7 голосов
/ 03 апреля 2009

К сожалению, нет. Там нет.

5 голосов
/ 27 января 2015

Я знаю, что это очень старый вопрос, но поскольку принятый ответ неверен, я чувствую себя обязанным опубликовать свой собственный. Я буду использовать пример принятого ответа, слегка измененный. (Предполагая, что перечисления являются последовательными.)

// 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 голосов
/ 10 декабря 2011
int enaumVals[] =
{
FIRST,
SECOND,
THIRD,
LAST
};

#define NUM_ENUMS sizeof(enaumVals) / sizeof ( int );
3 голосов
/ 03 апреля 2009

Ну, поскольку перечисления не могут меняться во время выполнения, лучшее, что вы можете сделать, это:

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

Но мне трудно представить себе ситуацию, когда эта информация пригодится. Что именно вы пытаетесь сделать?

0 голосов
/ 08 марта 2018
#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 голосов
/ 09 августа 2016

Попробуйте это:

enter image description here

Это ужасно, и могут быть некоторые компиляторы, которым это не нравится, но обычно это работает и полезно. Вы можете использовать его для каждого типа перечисления.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...