特殊使用C宏

时间:2012-07-09 04:50:34

标签: c enums constants preprocessor

读取C库的套接字接口的代码,我发现了这个:

/* Types of sockets.  */
enum __socket_type
{
   SOCK_STREAM = 1,     /* Sequenced, reliable, connection-based
               byte streams.  */
#define SOCK_STREAM SOCK_STREAM
   SOCK_DGRAM = 2,      /* Connectionless, unreliable datagrams
               of fixed maximum length.  */
#define SOCK_DGRAM SOCK_DGRAM
...

这个“成语”遍布bit / socket.h。我只是很好奇,那些宏的目的是什么?

3 个答案:

答案 0 :(得分:6)

这些常量过去只是#define s,所以你所看到的可能就是保护你不会意外地混合旧的和新的头文件。使用enum定义常量的一个优点是enum成员往往在调试器中可用,而#define宏则不可用。

如果您(意外地)包含了一些其他尝试#define SOCK_STREAM的头文件,您将收到编译器警告,而不是静默使用可能不正确的值。

更新

通过glibc git repo查看,我发现了添加#define s的具体提交,并附有以下评论:

* sysdeps/generic/socketbits.h: Also make SOCK_* constants available
as macros so that #ifdef works.
* sysdeps/unix/sysv/linux/socketbits.h: Likewise.

你有它。

答案 1 :(得分:2)

这是“enum”的C等价物。

逻辑套接字类型“stream”(SOCK_STREAM)对应于二进制值“1”。 “数据报”(SOCK_DGRAM)是类型“2”。等

“套接字”是在“enum”成为C语言的一部分之前发明的。

上述习语允许您在代码中使用“SOCK_STREAM”(例如);它还允许您使用“#ifndef SOCK_STREAM”(这在某些遗留程序中可能很重要)。

答案 2 :(得分:1)

历史系统使用宏并且没有这样的枚举。

旧版本的POSIX / Single Unix(例如SUSv3)强制SOCK_xxx为宏。这意味着这些常量可以用在预处理程序指令中(例如#ifdef SOCK_DGRAM)。这有时可以在构建时检查系统是否支持非标准套接字类型。

较新的标准(例如SUSv4)放宽了对系统的要求:SOCK_xxx常量可以是任何类型的symbolic constants。这包括预处理器宏以及产生常量表达式的任何其他类型的定义(适用于静态初始化器和需要常量表达式的其他上下文),例如枚举常量。

您正在查看的实施符合SUSv3(SUSv4,SUSv3合规性意味着在这方面符合SUSv4)。仅定义枚举而不是常量的实现将符合SUSv4但不符合SUSv3。

定义枚举的优点是,如果在不调用一个的上下文中使用SOCK_xxx常量,或者如果使用任意整数,它允许编译器提供适当的反馈。预计会有SOCK_xxx值。

许多类似的常量也是如此。