在C语言中,说“#define FOO FOO”的意义是什么?

15

我遇到了一些C代码,作者在很多地方都使用以下习惯用法:

typedef __int32 FOO_INT32;
#define FOO_INT32 FOO_INT32

这样做的意义是什么?typedef 不应该足够吗?这是一些奇怪的 C 编译器的解决方法吗?


随意将此问题标记为已回答 ;) - claf
4个回答

29

使用#define指令,您就可以通过以下方式测试是否在代码的其他地方执行了typedef:

#ifdef FOO_INT32
FOO_INT32 myfoo;
#else
int myfoo;
#endif

3

有时候在头文件中会使用这种做法。#define 允许在编译时测试 typedef 的存在性。这样可以写出像下面这样的代码:

#ifdef FOO_INT32
FOO_INT32 myfoo;
#else
int myfoo;
#endif

或者作为真正的守卫 #define,类似于头文件守卫。

#ifndef FOO_INT32
typedef int FOO_INT32
#define FOO_INT32 FOO_INT32
#endif

这并不是一个好的做法,但它有其用途,特别是当您有一些使用其他库定义类型的标题时,但在您根本不使用这些库的情况下,您希望提供自己的替代方案。


我猜如果在typedef之前有#ifndef FOO_INT32,他会猜测使用它作为守卫。 - user65636

2
另一个原因是标准可能要求将定义转换为宏。以下是取自glibc的片段:netinet/in.h
/* Standard well-defined IP protocols.  */
enum
  {
    IPPROTO_IP = 0,    /* Dummy protocol for TCP.  */
#define IPPROTO_IP      IPPROTO_IP
    IPPROTO_ICMP = 1,      /* Internet Control Message Protocol.  */
#define IPPROTO_ICMP        IPPROTO_ICMP
    IPPROTO_IGMP = 2,      /* Internet Group Management Protocol. */
#define IPPROTO_IGMP        IPPROTO_IGMP

这里的枚举符号也按照相关的POSIX规范要求导出为宏,如引用所示:

The header shall define the following macros for use as values of the level argument of getsockopt() and setsockopt():

IPPROTO_IP

Internet protocol.

IPPROTO_IPV6

Internet Protocol Version 6.

...


1
这种模式也适用于微处理器中寄存器的特征检测,例如this question。例如,可能有两个类似的头文件,一个定义了一个计时器,另一个定义了两个计时器:

cheapprocessor.h:

#define TMR1 TMR1
extern volatile int TMR1;

expensiveprocessor.h:

#define TMR1 TMR1
extern volatile int TMR1;
#define TMR2 TMR2
extern volatile int TMR2;

这意味着在您的主代码中,当您包含一个通用的processor.h文件并委托给目标适当的头文件时,您可以检测功能:
#include <processor.h>

#ifdef TMR2
    x = TMR2;
#else
    x = 0;  // no timer, probably because we're on the cheaper model
#endif

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接