用于枚举的宏的实用程序

时间:2014-02-18 13:28:40

标签: c c-preprocessor

我的Linux系统上的一个标题socket.h如下所示。

/* Bits in the FLAGS argument to `send', `recv', et al.  */
enum
  {
    MSG_OOB             = 0x01, /* Process out-of-band data.  */
#define MSG_OOB         MSG_OOB
    MSG_PEEK            = 0x02, /* Peek at incoming messages.  */
#define MSG_PEEK        MSG_PEEK
    MSG_DONTROUTE       = 0x04, /* Don't use local routing.  */
#define MSG_DONTROUTE   MSG_DONTROUTE
...

定义enum是一种idiom for creating type-safe-ish constants in C,该语言实际上将其视为编译时常量。

我的问题是:宏扩展到自己的宏MSG_OOBMSG_PEEK,......的定义有什么用途?

2 个答案:

答案 0 :(得分:7)

这些定义的目的是应用程序可以执行类似

的操作
#ifdef MSG_OOB
  some code here
#endif

宏的扩展不是递归的,因此对宏MSG_OOB的评估会产生同名的enum常量MSG_OOB

还要将声明为enum的常量帮助,例如在调试时。

答案 1 :(得分:6)

POSIX标准规定“符号常量”如MSG_DONTROUTE是“类似对象的宏”,而不是枚举。将它们定义为自身允许它们在枚举的上下文中使用,以及与例如#ifdef一起正常工作。

从POSIX标准:

  

标题应定义以下符号常量   ....   MSG_DONTROUTE

  

符号常量...指的是C预处理器符号(也没有参数)。

最后,来自附录:

  

如果一个常量需要是一个宏,但也允许它是另一种类型的常量,例如枚举常量,那么在将它定义为另一种常量的实现上,宏通常定义如下:

     

#define macro_name macro_name

     

这允许应用程序使用#ifdef等来确定宏是否已定义,但宏在#if预处理程序指令中不可用,因为预处理器会将未展开的单词macro_name视为值为零。