简体   繁体   中英

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.

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();

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

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;
}

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
}

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?

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");
    }
  }
}

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
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM