Проверьте, определено ли значение в перечислении C?
предполагая, что у меня есть это:
enum { A = 0x2E, B = 0x23, C = 0x40 }
можно проверить, если x определена в enum?
я делаю это вручную: int isdef = (x == A || x == B || x == C); но я хочу что-то более динамичное. GCC-extensions тоже приветствуются.
6 ответов
Это своего рода модифицированная версия вашего вопроса, но в зависимости от того, что вы делаете, что-то вроде этого может сработать:
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");
}
выходы
Value of A: 0x2e isEnum(0x2e): true isEnum(0x2f): false
EDIT: TJD опередил меня, и его предложение использовать отсортированный массив и выполнять двоичный поиск уменьшило бы время поиска с n войти(n).
Не насколько мне известно. Перечисление в C - это просто более чистая альтернатива серии
#define A 0x2E
заявления.
если перечисление велико и его значения непрерывны, объявите константы min/max и сравните с ними:
enum { E_MIN = 0x2E, A = 0x2E, B = 0x23, C = 0x40 ..., E_MAX=0x100};
if(x >= MIN && x <= MAX)
    ItsInEnum();
самый простой способ сделать это:
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
}
чтобы развернуть принятый ответ, используйте X-макросы для построения перечисления и массива из одних и тех же данных с помощью препроцессора.
/* 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;
}
An enum по сути то же самое, что использование макросов для определения констант, за исключением того, что enum обертывания набор связанных констант в тип данных.  Это делает ваш код более самодокументированным, но на самом деле не предоставляет никаких дополнительных функций.
если вы выходите за рамки стандартного C, некоторые компиляторы могут делать дополнительные вещи с enum что они не могут сделать с макросами.  Некоторые отладчики будут отображать enum переменные возвращаются к своему имени вместо показывая свою ценность.  Кроме того, некоторые компиляторы предоставляют возможность добавлять проверки во время выполнения Для таких вещей, как out-of-bounds enum значения.  Это по сути то же самое, что и код, который вы показываете, только компилятор добавляет его автоматически.  С компилятором C GreenHills эта функция включена с помощью -check=assignbound опции компилятора.  Я не уверен, есть ли у gcc что-то вроде этого встроенного или нет.  Какой компилятор вы используете?
Как уже указывалось, невозможно проверить, определено ли перечисление путем прямой ссылки на член перечисления. Однако существует очень простой ярлык: определите уникальный идентификатор, связанный с каждым перечисляемым типом. Затем, если вы хотите проверить, существует ли элемент перечисления, вы можете просто проверить, определен ли связанный идентификатор:
//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
}
