Предположим, что "пустое" определение макроса
#define FOO
Действительно ли стандарт C? Если да, то что такое FOO
после этого определения?
Предположим, что "пустое" определение макроса
#define FOO
Действительно ли стандарт C? Если да, то что такое FOO
после этого определения?
Это просто макрос, который расширяется, ну, ничего. Однако теперь, когда макрос был определен, вы можете проверить с помощью #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
, и вы не увидите сообщение.
Да, пустой стандарт разрешен стандартом.
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
Пустые определения макросов также могут использоваться для самостоятельной документации. 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
);