Подтвердить что ты не робот

Разрешены ли пустые определения макросов в C? Как они себя ведут?

Предположим, что "пустое" определение макроса

#define FOO

Действительно ли стандарт C? Если да, то что такое FOO после этого определения?

4b9b3361

Ответ 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
  );