在C中说“#define FOO FOO”有什么意义?

时间:2009-03-11 22:13:38

标签: c c-preprocessor

我遇到了一些 C 代码,其中作者在整个地方使用以下习语:

typedef __int32 FOO_INT32;
#define FOO_INT32 FOO_INT32

这样做有什么意义? typedef不应该足够吗?对于一些不太好的 C 编译器来说,这是一种解决方法吗?

4 个答案:

答案 0 :(得分:28)

使用#define指令,您将能够使用以下代码测试typedef是否已在代码中的其他位置完成:

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

答案 1 :(得分:2)

这种做法有时候会在标题中完成。 #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

这不一定是一个好的做法,但它有其用途,特别是当你有一些标题使用其他库定义的类型时,但是当你根本不使用那些库时,你想提供自己的替代案例

答案 2 :(得分:1)

此模式对于微处理器中寄存器的特征检测也很有用,如this question中所示。例如,可能有两个类似的头文件,其中一个定义了一个定时器,另一个定义了2:

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

答案 3 :(得分:1)

另一个原因是标准可能要求定义为宏。

来自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

此处枚举符号也会根据the relevant POSIX spec的要求导出为宏,引用:

  

标题应定义以下宏用作   getsockopt()和setsockopt()的level参数的值:

     

IPPROTO_IP

Internet protocol.
     

IPPROTO_IPV6

Internet Protocol Version 6.
     

...