web-dev-qa-db-fra.com

Les définitions de macro vides sont-elles autorisées en C? Comment se comportent-ils?

Supposons que la définition de macro "vide"

#define FOO

Est-ce une norme C valide? Si oui, qu'est-ce que FOO après cette définition?

40
user1150105

C'est simplement une macro qui se développe, enfin, rien. Cependant, maintenant que la macro a été définie, vous pouvez vérifier avec #if defined (Ou #ifdef) Si elle a été définie.

#define FOO

int main(){
    FOO FOO FOO
    printf("Hello world");
}

va s'étendre à

int main(){

    printf("Hello world");
}

Il existe certaines situations où cela est très pratique, par exemple des informations de débogage supplémentaires, que vous ne souhaitez pas afficher dans votre version:

/* 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");
    /* ... */
}

Puisque la macro CONFIG_USE_DEBUG_MESSAGES A été définie, DEBUG_MSG(x) se développera en print(x) et vous obtiendrez Entering main. Si vous supprimez la #define, DEBUG_MSG(x) se développe en une boucle do-while vide et vous ne verrez pas le message.

48
Zeta

Oui, la définition vide est autorisée par la norme.

C11 (n1570), § 6.10 Directives de prétraitement

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)

Les gardes d'inclusion sont une utilisation courante.

#ifndef F_H
# define F_H

#endif
20
md5

Les définitions de macro vides peuvent également être utilisées pour l'auto-documentation. IN dans l'extrait de code ci-dessous est un exemple. Le code et le commentaire sont tous deux extraits du projet 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
  );
1
smwikipedia