簡體   English   中英

在 C 中聲明枚舉類型標簽和變量名的好用例?

[英]Good use cases for declaring enum type tags and variable names in C?

如果您的代碼中需要一些常量,您可以使用枚舉聲明它們:

enum {
    DOG,
    CAT,
    FISH,
};

enum {
    CAR,
    BUS,
    TRAIN,
};

然后根據需要使用DOGBUS等。 但是枚舉也可以用更詳細的樣式聲明:

enum animals {
    DOG,
    CAT,
    FISH,
} pets;

enum transport {
    CAR,
    BUS,
    TRAIN,
} vehicles;

鑒於枚舉常量具有全局范圍並且不能像結構和聯合那樣被pets.DOG引用, pets.DOG詳細樣式有什么好的用例嗎? 對我來說,枚舉的類型標簽和變量名看起來很多余,甚至令人反感,因為它們看起來像結構,但不能像結構一樣使用。 我希望我遺漏了一些東西,它們確實有很好的用處。

有一個相關的SO Q&A ,其中最重要的假設是在使用枚舉時會使用類型標記和變量名稱。 所以我的問題可以重申為“如果我只使用匿名枚舉,我會在哪些任務中失敗?” 因為對我來說,枚舉的全部意義在於DOGCATCAR常量,我認為將其中之一分配給枚舉變量沒有用。 我還在學習,所以我確定我一定遺漏了一些東西。

如果您想聲明該類型的變量,您可以為enum類型命名:

enum animals a1 = DOG;
enum animals a2 = CAT;

或者將它們作為函數參數:

void foo(enum animals a);

雖然枚舉被認為是整數類型,並且您也可以使用int來存儲這些值之一,但使用enum類型的變量有助於記錄您的代碼並使您的意圖對讀者清晰。

“對我來說,枚舉的類型標簽和變量名看起來很多余......”

以枚舉列表 ( enum ) 的形式使用命名整數值的順序集合的價值乍一看似乎很微妙,但由於以下幾個原因,在 C 項目中使用時變得非常明顯:

  • The names associated with an enumerated list provide self-documenting code, ie particularly when collection of names chosen to represent a set of enumerated values forms a theme related to the task at hand. (你的動物enum是一個很好的例子,用於枚舉例如大量命令或公司內的職位類型。)
  • 枚舉列表中值的默認分配是順序的,從 0 開始,遞增 1 直到列表末尾,從而產生唯一值列表,非常適合在通過具有特定含義的字符串數組進行索引時使用,或者當在switch語句中用作每個case語句的常量整數值時。

關於評論: “......但是使用ANML類型而不是int的優勢是最小的,......”

  • enum列表還提供了記錄約束 例如使用ANML anml; 而不是int anml; 因為struct成員將快速向那些將維護/更新源代碼的人(在未來幾個月或幾年內。)指出該成員被限制使用的相關值的關聯列表,而不是任何隨機整數值. 這在使用枚舉列表時很重要,例如。 在 switch 語句中,該語句僅用於處理與該enum的常量整數值相對應的一組case語句。

這兩個一起是我發現特別有用的用例的一部分,即使用枚舉與字符串數組結合為用戶界面選擇內容,或用於子字符串搜索等。

例如:

typedef enum {
       CAT,
       DOG,
       FISH,
       MAX_ANML
    }ANML;//for use in struct

 char *strings[MAX_ANML] = {"cat","dog","fish"};

    typedef struct {
        char content[80];
        ANML anml;
    }SEARCH;

例如,這兩個結構可以與switch語句結合使用:

bool searchBuf(SEARCH *animal)
{
    bool res = FALSE;
    switch (animal->anml) {
        case CAT:
            //use the string animal[type] for a search, or user interface content, etc.
            if(strstr(animal->content, strings[CAT]))
                res = TRUE;
            break;
        case DOG:
            if(strstr(animal->content, strings[DOG]))
                res = TRUE;
            break;
        case FISH:
            if(strstr(animal->content, strings[FISH]))
                res = TRUE;
            break;
    };
    return res;
}

int main(void)
{
    char buffer[] = {"this is a string containing cat."};
    SEARCH search;
    strcpy(search.content, buffer);
    search.anml = CAT;

    bool res = searchBuf(&search);
    //use res...

    return 0;    
}

我在調試時喜歡枚舉而不是 #defines。 debuer 不僅顯示數值,還顯示枚舉名稱 - 非常方便

在許多其他人發布了有用的答案和評論之后,我發布了我自己的答案,我們已經確定枚舉類型名和變量名作為自文檔代碼很有用,並使代碼的意圖清晰(感謝答案作者:ryyker 和 dbush)。

當我正在試驗並尋找使用非匿名枚舉的更有力的理由時,我確定不能有任何定義。 枚舉沒有范圍和邊界檢查,在編譯時 (GCC 6) 和運行時都沒有。 這是一個演示弱點的片段:

enum withType { // enum with type name and variable name
    ONE,
    TWO,
    THREE,
} wtEnum;

enum { // Anonymous enum
    TINY,
    SMALL,
    MID,
    LARGE,
    BIGGEST,
};

int main(void) {
    enum withType wt1 = LARGE; // Overflow!
    wtEnum = BIGGEST; // Overflow!
    printf("Enum test values: %d, %d, %d\n", THREE, wt1, wtEnum);
    return 0;
};

該示例清楚地表明,您可能想要對枚舉類型名稱和變量名稱進行的任何“范圍界定”僅是約定俗成的,並且依賴於編碼人員的紀律,不要跨越枚舉“域”。 我什至聲稱,鑒於這一現實,C 中的枚舉功能是“設計錯誤的”。 它創造了我們在結構和聯合中看到的那種實用程序的印象,但沒有提供任何類似的東西。 在此洞察之后,我認為匿名枚舉是唯一可以使用的安全枚舉!

盡管如此,我已經接受了 ryyker 的回答,因為它很好地展示了枚舉的主流用法。 但我也在這里留下我自己的答案,因為我提出的觀點是有效的。

暫無
暫無

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

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