簡體   English   中英

檢查是否在C enum中定義了值?

[英]Check if a value is defined in an C enum?

假設我有這個:

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

可以檢查x是否定義為enum

我是手動完成的: int isdef = (x == A || x == B || x == C); 但我想要更有活力的東西。 GCC-extensions也是受歡迎的。

不是我所知道的。 C中的枚舉只是一系列更清晰的替代品

#define A 0x2E

聲明。

如果枚舉很大並且其值恰好是連續的,則聲明最小/最大常量並與之比較:

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

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

這是你問題的修改版本,但根據你正在做的事情,這樣的事情可能有效:

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

編輯:TJD打敗了我,他建議使用排序數組並進行二分查找會減少你從n到log( n )的搜索時間。

要擴展已接受的答案,請使用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;
}

最簡單的方法是:


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
}

enum與使用宏來定義常量基本相同,只是enum將一組關聯的常量包裝到數據類型中。 這使您的代碼更加自我記錄,但實際上並沒有提供任何其他功能。

如果你在標准C的范圍之外冒險,一些編譯器可以使用enum來做額外的事情,而不能用宏做。 一些調試器會將enum變量映射回其名稱,而不是顯示其值。 此外,一些編譯器提供了為諸如越界enum值之類的事物添加運行時檢查的能力。 這與您顯示的代碼基本相同,只有編譯器會自動添加它。 使用GreenHills的C編譯器,可以使用-check=assignbound編譯器選項啟用此功能。 我不確定gcc是否有類似內置的東西。 你用的是什么編譯器?

這是另一種可能的解決方案

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

正如已經指出的那樣,無法通過直接引用枚舉成員來檢查是否定義了枚舉。 但是,有一個非常簡單的快捷方式:定義與每個枚舉類型關聯的唯一標識符。 然后,當您要檢查枚舉的元素是否存在時,您只需檢查是否定義了關聯的標識符:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM