Количество элементов в перечислении

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

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

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

9 ответов

Решение

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

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

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

enum MyType {
  Type1,
  Type2,
  Type3,
  NumberOfTypes
}

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

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

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

К сожалению нет. Нет.

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

// 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 подразумевается, чтобы не быть частью предлагаемых предметов? Это выглядит странно для меня, но, думаю, это может иметь смысл...

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

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

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

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

#define NUM_ENUMS sizeof(enaumVals) / sizeof ( int );
#include <stdio.h>

// M_CONC and M_CONC_ come from https://stackru.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));
}

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

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

Другие вопросы по тегам