Разрешены ли пустые определения макросов в C? Как они себя ведут?
Предположим, что "пустое" определение макроса
#define FOO
Действительно ли стандарт C? Если да, то что такое FOO
после этого определения?
Ответы
Ответ 1
Это просто макрос, который расширяется, ну, ничего. Однако теперь, когда макрос был определен, вы можете проверить с помощью #if defined
(или #ifdef
), было ли оно определено.
#define FOO
int main(){
FOO FOO FOO
printf("Hello world");
}
будет расширяться до
int main(){
printf("Hello world");
}
Есть определенные ситуации, когда это очень удобно, например дополнительная отладочная информация, которую вы не хотите показывать в своей версии:
/* Defined only during debug compilations: */
#define CONFIG_USE_DEBUG_MESSAGES
#ifdef CONFIG_USE_DEBUG_MESSAGES
#define DEBUG_MSG(x) print(x)
#else
#define DEBUG_MSG(x) do {} while(0)
#endif
int main(){
DEBUG_MSG("Entering main");
/* ... */
}
Поскольку макрос CONFIG_USE_DEBUG_MESSAGES
был определен, DEBUG_MSG(x)
будет расширяться до print(x)
, и вы получите Entering main
. Если вы удалите #define
, DEBUG_MSG(x)
расширится до пустого цикла do
- while
, и вы не увидите сообщение.
Ответ 2
Да, пустой стандарт разрешен стандартом.
C11 (n1570), § 6.10 Директивы предварительной обработки
control-line:
# define identifier replacement-list new-line
# define identifier lparen identifier-list(opt) ) replacement-list new-line
# define identifier lparen ... ) replacement-list new-line
# define identifier lparen identifier-list , ... ) replacement-list new-line
replacement-list:
pp-tokens(opt)
Общим использованием является защита от включения.
#ifndef F_H
# define F_H
#endif
Ответ 3
Пустые определения макросов также могут использоваться для самостоятельной документации. IN
в фрагменте кода ниже - образец. Код и комментарий оба цитируются из проекта EDK II.
//
// Modifiers for Data Types used to self document code.
// This concept is borrowed for UEFI specification.
//
///
/// Datum is passed to the function.
///
#define IN
typedef
EFI_STATUS
(EFIAPI *EFI_BLOCK_RESET)(
IN EFI_BLOCK_IO_PROTOCOL *This,
IN BOOLEAN ExtendedVerification
);