簡體   English   中英

在枚舉之間選擇還是在C中定義?

[英]Choosing between enum or define in C?

我注意到libc中的大多數預定義值都是使用#define指令編寫的。 例如, whence參數在fseek中獲取一個int (據我所知) enum本來會更好。 有很多這樣的例子顯然應該出於某種原因(除了后兼容性問題)。

所以我想知道在哪種情況下使用#define更好,而enum是一種更容易被發現類型安全的替代品

作為一個實際例子,考慮一個表示輸入/輸出通道的typedef ,因為它可能是內核的情況。 gpio可以在輸入或輸出中配置。 在這里使用enum指令是否值得?

typedef struct gpio {
    size_t port; 
    size_t bit;
    enum { DIR_INPUT, DIR_OUTPUT } direction; // or `bool`?
    bool value;
} gpio;

請注意, enum可以用三種不同的方式實現:

i)類型:

typedef enum gpio_direction {   
   DIR_OUTPUT
   DIR_INPUT
} gpio_direction;

ii)全球枚舉

enum gpio_direction {   
   DIR_OUTPUT
   DIR_INPUT
} gpio_direction;

iii)匿名枚舉(如我的例子所示)。

有很多這樣的例子顯然應該存在是有原因的

一個原因是沒有可移植的方法來從匯編代碼中引用C enum 低級代碼通常(通常仍然是)用匯編語言編寫,因此低級代碼使用的常量將由#define而不是enum指定。

另一個原因是成語if (verbosity & WAKE_THE_NEIGHBOURS) ,其中#defined值用於指定位位置。

所以我想知道在哪種情況下使用#define更好,而枚舉是一種類型安全的替代方案,更容易被發現

在所有其他情況下,我(今天 - 使用#define也有點傳統)使用enum ,因此if (verbosity == RED)會引發警告(如果你使用例如gcc with -Wall )。

雖然人們可能應該使用其他可用的解決方案,但仍然存在需要宏的情況。 有些是歷史原因,但今天仍有其他原因。

例如,你提到了fseekwhence參數(即SEEK_SETSEEK_CUR和` SEEK_CUR )。 這些(由於歷史原因)被指定為標准中的宏 - 因此實現者必須將它們定義為完全符合的宏,一些邪惡的程序員可以編寫(並責怪庫的后果):

#include <stdio.h>

#ifndef SEEK_CUR
int evil = *(int*)0;
#endif

但據我所知,他們沒有理由不寫:

enum __WHENCE_T {
    __SEEK_CUR,
    __SEEK_END,
    __SEEK_SET
};

#define SEEK_CUR __SEEK_CUR
#define SEEK_END __SEEK_END
#define SEEK_SET __SEEK_SET

另一個歷史原因是編譯器在使用宏時可能產生了更高效的代碼。 當時寫的代碼可能仍然存在並且包含當時工作得更好的構造(並且今天仍然很好用)。

現代的原因是你需要使用C編譯器之外的值。 例如,如果您想在匯編程序代碼(或其他語言)中使用該值。 您需要做的就是確保標題不會擴展為某些內容(包含C代碼),除非它是使用C編譯器編譯的。 例如:

#define NUMBER 42

#ifdef __STDC__
extern int variable;

int function(void);
#endif

如果包含在匯編程序中,宏NUMBER仍然可以擴展(並擴展到與C程序相同的東西)。

暫無
暫無

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

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