Какой смысл говорить "#define FOO FOO" в C? - PullRequest
14 голосов
/ 12 марта 2009

Я столкнулся с кодом C , где автор повсеместно использует следующую идиому:

typedef __int32 FOO_INT32;
#define FOO_INT32 FOO_INT32

Какой смысл делать это? Разве typedef не должно быть достаточно? Это обходной путь для некоторых изощренных C компиляторов?

Ответы [ 4 ]

28 голосов
/ 12 марта 2009

С помощью инструкции #define вы сможете проверить, был ли typedef где-то еще в коде, используя:

#ifdef FOO_INT32
FOO_INT32 myfoo;
#else
int myfoo;
#endif
2 голосов
/ 12 марта 2009

Это практика, которая иногда выполняется в заголовках. #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

Это не обязательно хорошая практика, но она имеет свои применения, особенно когда у вас есть некоторые заголовки, которые используют типы, определенные другими библиотеками, но вы хотите предоставить свои собственные замены для случаев, когда вы вообще не используете эти библиотеки .

1 голос
/ 14 мая 2017

Другая причина в том, что стандарт может требовать, чтобы определения были макросами.

Фрагмент из 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 , цитата:

Заголовок должен определять следующие макросы для использования в качестве значения аргумента уровня getsockopt () и setsockopt ():

IPPROTO_IP

Internet protocol.

IPPROTO_IPV6

Internet Protocol Version 6.

...

1 голос
/ 14 ноября 2016

Этот шаблон также полезен для обнаружения признаков регистров в микропроцессорах, как в этот вопрос . Например, может быть два одинаковых заголовочных файла, один из которых определяет один таймер, а другой определяет 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
...