Macro de préprocesseur C non correct

Pour la journalisation de débogage, j’ai souvent vu et utilisé quelque chose comme:

#ifdef DEBUG #define DLOG(fmt, args...) printf("%s:%d "fmt,__FILE__,__LINE__,args) #else #define DLOG(fmt, args...) #endif 

mais dans un certain nombre d’endroits, j’ai vu le deuxième #define remplacé par

 #define DLOG(fmt, args...) do {} while (0) 

En particulier, il y a cette réponse , et le commentaire sur cette autre réponse à la même question suggère que le problème serait dans une situation telle que

 if (condition) DLOG("foo"); 

Bien que mon test rapide suggère que le point-virgule résultant sur la ligne à lui seul servira d’instruction no-op à l’intérieur du conditionnel.

Est-ce que l’un ou l’autre est néant et do {} while (0) meilleur? Si oui, pourquoi? Y a-t-il autre chose qui est encore meilleur?

Voir la macro C #define pour l’impression de débogage pour une explication de la raison pour laquelle vous voulez une forme différente de non-op. Vous souhaitez que le compilateur parsing le code d’impression de débogage même lorsque vous ne l’utilisez pas afin que les erreurs ne s’insinuent pas.

Un point-virgule à lui seul présente deux inconvénients:

  • Les utilisateurs de votre macro peuvent l’écrire sans point-virgule et le compilateur ne se plaindra pas.
  • Certains compilateurs peuvent émettre un avertissement concernant un point-virgule potentiellement errant.

L’astuce do {} while (0) répond à ces deux préoccupations:

 DLOG("foo") // No semicolon 

déclenchera une erreur et le compilateur ne vous avertira pas d’un point-virgule “errant”.

La réponse rapide est que la méthode do / while vous permet de remplacer plusieurs instructions et de les utiliser comme une seule instruction dans un cas similaire à celui de votre question. Pour le remplacement d’une seule expression, je ne pense pas qu’il y ait de différence.