L'utilisation de macros C / C ++ comme raccourci pour la compilation conditionnelle est-elle une bonne pratique?

13

Disons que je veux avoir plusieurs types de messages de sortie dans mon code. L'un d'eux est DEBUG, qui est imprimé uniquement, lorsque le code est compilé en mode débogage.

Habituellement, je devrais écrire quelque chose comme

#ifdef DEBUG
    std::cout << "Debug message" << std::endl;
#endif

ce qui est assez lourd et ennuyeux à utiliser dans de nombreux endroits.

Est-ce une bonne pratique de définir une macro pour l'extrait de code, donc vous l'utiliseriez de cette façon?

MSG_DEBUG("Debug message")

Ou existe-t-il une autre manière plus élégante de gérer cela sans macros? Je m'intéresse aux solutions possibles en C et C ++, car j'utilise les deux langages dans différents projets.

Eenoku
la source
Il n'est pas clair à la question de savoir pourquoi vous ne mettriez pas simplement le code conditionnel dans une fonction et l'appelleriez. Y a-t-il une autre contrainte qui empêcherait cela?
Alex
@gnat La question que vous avez mentionnée est si large que la plupart des gens ne le relieraient pas à ce sujet, surtout lorsqu'ils chercheraient cette question spécifique sur Internet.
Eenoku
3
Votre question est balisée avec c et c ++ , cependant, ce sont des langages assez différents. Pouvez-vous préciser de quoi vous parlez? Votre exemple serait parfaitement bien en C, mais pourrait être mieux implémenté avec un constexpr ifen C ++, par exemple.
Jörg W Mittag
1
En passant, les diagnostics devraient aller à STDERR. Aussi, pourquoi ne pas le faire dépendre NDEBUGcomme assert()ça à la place? Ensuite, vous pouvez le définir comme #define DEBUG_MSG(MSG) assert(std::cerr << MSG), qui teste également l'état du flux.
Déduplicateur

Réponses:

19

Bien sûr, si vous êtes d'accord avec l'utilisation de macros en premier lieu, alors en définir une paramétrisée plutôt que de continuer à répéter le même code conditionnel est certainement préférable par toute mesure de bon codage.

Devez-vous utiliser des macros? À mon avis, vous devriez, car c'est une pratique acceptée en C, et toute solution sans macro nécessiterait au moins quelque chose d' être exécuté même en dehors du mode débogage. Le programmeur C typique choisira à tout moment une macro légèrement moche sur un effort d'exécution inutile.

Kilian Foth
la source
13

Il y a un élément de préférence personnelle ici, mais en C ++, je préfère le faire dans le fichier d'en-tête:

#ifdef _DEBUG
    void DebugMessage(...);
#else
    inline void DebugMessage(...) {}
#endif

Pour que la fonction soit en ligne dans les versions, mais est une fonction appropriée dans la version de débogage afin que vous puissiez avoir une vérification de type appropriée, des messages d'erreur sensibles, etc. et la possibilité d'ajouter plus de fonctionnalités (journalisation peut-être?) Plus tard.

De toute évidence, vous devez également insérer la définition correspondante de la fonction dans le .cppfichier dans un #ifdef _DEBUGbloc.

Jack Aidley
la source
Mais les frais généraux d'appel sont toujours présents ici, n'est-ce pas?
Eenoku
7
Si votre compilateur génère du code pour appeler une fonction vide connue dans une version, la première et la plus importante chose à faire pour améliorer l'efficacité est d'obtenir un compilateur bien meilleur. C'est une optimisation vraiment banale.
David Thornley
@Eenoku Non, comme le dit David, il sera supprimé par tout compilateur que vous devriez utiliser.
Jack Aidley
3
Il y a une différence clé ici: la macro (selon la façon dont elle est écrite) n'évaluerait pas ses expressions d'argument, tandis que la fonction le ferait toujours. En outre, c'est un comportement indéfini de passer des arguments non triviaux aux fonctions varargs (et déclenche généralement des avertissements du compilateur).
Sebastian Redl
2

Certainement, assurez-vous simplement que vous ne respectez pas les directives de code données par votre équipe. Assurez-vous qu'aucun autre code du système n'essaye d'atteindre la même fonctionnalité via une condition if générale.

James O
la source