web-dev-qa-db-fra.com

Nombre d'éléments dans une énumération

En C, existe-t-il un bon moyen de suivre le nombre d'éléments dans une énumération? j'ai vu

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

Mais cela ne fonctionne que si les éléments sont séquentiels et commencent à zéro.

39
Peter Gibson

Je ne crois pas qu'il y en ait. Mais que feriez-vous avec un tel nombre s’ils ne sont pas séquentiels et que vous n’en avez pas déjà la liste quelque part? Et si elles sont séquentielles mais commencent à un numéro différent, vous pouvez toujours faire:

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

Si vous n'affectez pas vos enums, vous pouvez faire quelque chose comme ceci:

enum MyType {
  Type1,
  Type2,
  Type3,
  NumberOfTypes
}

NumberOfTypes sera évalué à 3, ce qui correspond au nombre de types réels.

64
vpicaver

Vieille question, je sais. Ceci est pour les googlers avec la même question.

Vous pouvez utiliser X-Macros

Exemple:

//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

Ceci est également transparent pour un IDE, donc l'auto-complétion fonctionnera correctement (comme c'est tout fait dans le pré-processeur).

19
Sam

Malheureusement non. Il n'y a pas.

7
rlbond

Je sais que la question est très ancienne, mais comme la réponse acceptée est fausse, je me sens obligé de poster la mienne. Je vais réutiliser l'exemple de réponse accepté, légèrement modifié . (En supposant que les énumérations sont séquentielles.)

// 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.

Tout développeur en connaît la raison: count = last - first + 1..__ Et cela fonctionne avec n'importe quelle combinaison de signes (les deux extrémités sont négatives, les deux positives, ou uniquement la première extrémité négative). Tu peux essayer.

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

Edit: en relisant le texte, j'ai eu un doute. Est-ce que END signifiait ne pas faire partie des articles proposés? Cela me semble bizarre, mais bon, je suppose que ça pourrait avoir un sens ...

5
David Stosik

Eh bien, comme les enums ne peuvent pas changer au moment de l'exécution, la meilleure chose à faire est de:

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

Mais je trouve difficile d’envisager une situation dans laquelle cette information serait utile. Qu'est-ce que vous essayez de faire exactement?

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

#define NUM_ENUMS sizeof(enaumVals) / sizeof ( int );
2
iuoi
#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
mathedpotatoes