Jack
Jack

Reputation: 16724

Check if a value is defined in an C enum?

Assuming that I have this:

enum { A = 0x2E, B = 0x23, C = 0x40 }

it's possible check if x is defined into enum?

I'm doing it manually: int isdef = (x == A || x == B || x == C); But I want to something more dynamic. GCC-extensions are welcome too.

Upvotes: 14

Views: 48865

Answers (7)

Here is another possible solution:

#include <stdio.h>
#include <stdint.h>

typedef enum {
  VALUE_1 = 0x01,
  VALUE_2 = 0x03,
  VALUE_3 = 0x0A
} values_e;

int main(void)
{
  int a = 0;
  values_e vlr;

  for (int i = 0; i < 10; i++) {
    scanf("%d", &a);

    vlr = (values_e)a;
    switch (vlr) {
      case VALUE_1:
        printf("do ... value 1:\r\n");
        break;

      case VALUE_2:
        printf("do ... value 2:\r\n");
        break;

      case VALUE_3:
        printf("do ... value 3:\r\n");
        break;

      default:
        printf("ops...\r\n");
    }
  }
}

Upvotes: 1

Tim Ellis
Tim Ellis

Reputation: 1

As already pointed out, it is not possible to check if an enum is defined by directly referring to an enum member. However, there is a very simple shortcut: define a unique identifier associated with each enumerated type. Then, when you want to check if an element of the enumeration exists, you can simply check if the associated identifier is defined:

//Header File:
typedef enum 
{
   ENUM_ELEMENT_1 = 0,
   ENUM_ELEMENT_2 = 1,
   ENUM_ELEMENT_3 = 2,
   ENUM_ELEMENT_MAX
} eEnumElement;

#define ENUM_ELEMENT_DEFINED  1

...

//Source file:
void TaskOperateOnEnums(void) 
{
   #if defined(ENUM_ELEMENT_DEFINED)
   eEnumElement Test = ENUM_ELEMENT_1;
   ...
   #endif
}

Upvotes: 0

Luke Kowald
Luke Kowald

Reputation: 111

The easiest way to do this is:


enum {
    MODE_A,
    MODE_B,
    MODE_C
};

int modeValid(int mode)
{
    int valid = 0;

    switch(mode) {
        case MODE_A:
        case MODE_B:
        case MODE_C:
            valid = 1;
    };

    return valid;
}

void setMode(int mode)
{
    if (modeValid(mode)) {
        // Blah, blah
    }
}

int main(void)
{
    setMode(1);   // Okay
    setMode(500); // Error
}

Upvotes: 11

jedwards
jedwards

Reputation: 30210

This is kind of a modified version of your question, but depending on what you're doing, something like this might work:

enum {A,B,C};
const int E[] = {0x2E,0x23,0x40};
// Or:
// enum { A = 0x2E, B = 0x23, C = 0x40 };
// const int E[] = {A,B,C};

int isEnum(int x)
{
    for(int i=0; i<(sizeof(E)/sizeof(*E)); i++)
    {
        if(E[i] == x){ return 1; }
    }
    return 0;
}

int main(void)
{
    printf("Value of A: 0x%02x\n", E[A]);
    // Or:   
    // printf("Value of A: 0x%02x\n", A);

    printf("isEnum(0x2e): %s\n", isEnum(0x2e) ? "true" : "false");
    printf("isEnum(0x2f): %s\n", isEnum(0x2f) ? "true" : "false");
}

which outputs

Value of A: 0x2e
isEnum(0x2e): true
isEnum(0x2f): false

EDIT: TJD beat me to it, and his suggestion of using a sorted array and doing binary search would decrease your search time from n to log(n).

Upvotes: 13

AaronDanielson
AaronDanielson

Reputation: 2470

To expand on the accepted answer, use X-macros to build your enum and array from the same data using the preprocessor.

/* Only need to define values here. */
#define ENUM_VALUES \
    X(A, 0x2E)  \
    X(B, 0x23)  \
    X(C, 0x40)

/* Preprocessor builds enum for you */
#define X(a, b) a = b,
    enum {
        ENUM_VALUES
    };
#undef X

/* Preprocessor builds array for you */
#define X(a, b) a,
    const int E[] = {
        ENUM_VALUES
    };
#undef X

/* Copied from accepted answer */
int isEnum(int x)
{
    for(int i=0; i<sizeof(E);i++)
    {
        if(E[i] == x){ return 1; }
    }
    return 0;
}

Upvotes: 8

bta
bta

Reputation: 45057

An enum is essentially the same thing as using macros to define constants, except that the enum wraps a set of associated constants up into a data type. This makes your code more self-documenting, but doesn't really provide any additional functionality.

If you venture outside the realm of standard C, some compilers can do extra things with enum that they can't do with macros. Some debuggers will map enum variables back to their name instead of showing their value. Also, some compilers provide the ability to add run-time checks for things like out-of-bounds enum values. This is essentially the same as the code you show, only the compiler adds it automatically. With GreenHills' C compiler, this feature is enabled with the -check=assignbound compiler option. I'm not sure if gcc has something like this built-in or not. What compiler are you using?

Upvotes: 1

Seva Alekseyev
Seva Alekseyev

Reputation: 61351

Not to the best of my knowledge. An enum in C is just a cleaner alternative to a series of

#define A 0x2E

statements.

If the enum is large and its values happen to be continuous, declare min/max constants and compare to those:

enum { E_MIN = 0x2E, A = 0x2E, B = 0x23, C = 0x40 ..., E_MAX=0x100};

if(x >= MIN && x <= MAX)
    ItsInEnum();

Upvotes: 13

Related Questions