12

假设我有这个:

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

可以检查是否x定义为enum

我是手动做的:int isdef = (x == A || x == B || x == C);但我想要一些更有活力的东西。GCC-extensions也欢迎。

4

7 回答 7

13

据我所知,不是。C 中的枚举只是一系列

#define A 0x2E

陈述。

如果枚举很大并且它的值恰好是连续的,则声明最小/最大常量并与这些常量进行比较:

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

if(x >= MIN && x <= MAX)
    ItsInEnum();
于 2012-06-14T20:41:10.697 回答
12

这是您问题的一种修改版本,但取决于您在做什么,这样的事情可能会起作用:

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

哪个输出

A的值:0x2e
isEnum(0x2e): 真
isEnum(0x2f): 假

编辑:TJD 击败了我,他建议使用排序数组并进行二进制搜索,这会将您的搜索时间从n减少到 log( n )。

于 2012-06-14T20:55:45.560 回答
11

最简单的方法是:


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
}
于 2016-04-10T02:47:32.807 回答
7

要扩展已接受的答案,请使用 X-macros 使用预处理器从相同数据构建枚举和数组。

/* 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;
}
于 2014-04-10T17:58:04.510 回答
1

Anenum本质上与使用宏定义常量相同,只是enum将一组关联的常量包装成一个数据类型。这使您的代码更具自我记录性,但并没有真正提供任何附加功能。

如果您在标准 C 领域之外冒险,一些编译器可以做一些enum他们不能用宏做的额外事情。一些调试器会将enum变量映射回它们的名称,而不是显示它们的值。此外,一些编译器提供了添加运行时检查的能力,例如越界enum值。这与您显示的代码基本相同,只是编译器会自动添加它。使用 GreenHills 的 C 编译器,此功能通过-check=assignbound编译器选项启用。我不确定 gcc 是否有这样的内置功能。你用的是什么编译器?

于 2012-06-14T21:58:21.520 回答
1

这是另一种可能的解决方案:

#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");
    }
  }
}
于 2019-08-06T13:15:42.993 回答
0

正如已经指出的,无法通过直接引用枚举成员来检查枚举是否定义。但是,有一个非常简单的捷径:为每个枚举类型定义一个唯一标识符。然后,当您要检查枚举的元素是否存在时,您可以简单地检查关联的标识符是否已定义:

//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
}
于 2017-04-04T10:37:52.533 回答