Имя макроса и список замещения совпадают

Я нашел несколько директив предварительной обработки, в которых имя макроса и список замещения совпадают. Например, некоторые директивы предварительной обработки в stdbool.h предоставлены gcc.

#else /* __cplusplus */

/* Supporting <stdbool.h> in C++ is a GCC extension.  */
#define _Bool   bool
#define bool    bool
#define false   false
#define true    true

#endif /* __cplusplus */

Я не понимаю, почему программист написал эти директивы предварительной обработки. Они бесполезны, и замены будут терять время. Я знаю, что это не вызывает бесконечной рекурсии. Как избежать бесконечной рекурсии? Каковы соответствующие положения в стандарте C?

3

Решение

Бесконечная рекурсия во время замены макроса предотвращается стандартным разделом 16.3.4 раздела C ++ 11:

Если имя заменяемого макроса найдено во время этого сканирования списка замены (не включая
остальные токены предварительной обработки исходного файла), он не заменяется. Кроме того, если есть вложенные замены
встретить имя заменяемого макроса, он не заменяется. Эти не замененные токены предварительной обработки имен макросов больше не доступны для дальнейшей замены, даже если они позднее (повторно) рассматриваются в контекстах
в котором в противном случае токен предварительной обработки имени макроса был бы заменен.

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

Причина того, что true, bool, а также false определяются как макросы расширением GCC, чтобы сделать код C ++ более совместимым с C99. В C99 они определены как макросы в stdbool.h, поэтому код может проверить, определены ли они, например, с помощью #ifdef bool,

5

Другие решения

В дополнение к другим ответам, определение этих макросов поможет компилятору генерировать сообщения об ошибках «переопределения макросов», если у кого-либо есть отличная идея переопределить bool, true или false.

См. Стандартный раздел 16.3 — в переопределениях макросов допускаются только идентичные списки замены.

2

Расширения макросов не повторяются, поэтому они прекращаются.

Одним из преимуществ наличия макроса является то, что вы можете проверить его в препроцессоре

#if defined bool
...
#endif

работает только если bool это макрос.

1

Иногда стандарт говорит:X должен быть макрос. «Если ваш язык уже имеет встроенную Xнадо сказать #define X X быть стандартным. (Например, пользователь может сказать #ifdef X и ожидайте, что это будет правдой.)

Пример (C11, 7.2 / 2):

assert макрос должен быть реализован как макрос, а не как фактическая функция. Если
определение макроса подавляется для доступа к реальной функции, поведение
не определено.

Вполне вероятно, что ваша реализация будет иметь assert функция.

Для забавы, вот некоторые вещи, которые «не определены» относительно того, являются ли они макросами или идентификаторами с внешней связью:

  • errno

  • setjmp

  • va_copy, va_end

  • putc, getc

1
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector