124 votes

#ifdef vs #if - quelle est la meilleure/la plus sûre méthode pour activer/désactiver la compilation de sections particulières du code ?

Il s'agit peut-être d'une question de style, mais il y a une certaine division au sein de notre équipe de développement et je me demandais si quelqu'un d'autre avait des idées sur le sujet...

En fait, nous avons des instructions d'impression de débogage que nous désactivons pendant le développement normal. Personnellement, je préfère faire ce qui suit :

//---- SomeSourceFile.cpp ----

#define DEBUG_ENABLED (0)

...

SomeFunction()
{
    int someVariable = 5;

#if(DEBUG_ENABLED)
    printf("Debugging: someVariable == %d", someVariable);
#endif
}

Certains membres de l'équipe préfèrent cependant les suivantes :

// #define DEBUG_ENABLED

...

SomeFunction()
{
    int someVariable = 5;

#ifdef DEBUG_ENABLED
    printf("Debugging: someVariable == %d", someVariable);
#endif
}

...laquelle de ces méthodes vous semble la meilleure et pourquoi ? Mon sentiment est que la première est plus sûre car il y a toujours quelque chose de défini et il n'y a pas de danger que cela détruise d'autres définitions ailleurs.

0 votes

Note : con #if vous pouvez également utiliser #elif de manière cohérente, contrairement à #ifdef . Ainsi, au lieu d'utiliser simplement #define BLAH utiliser #define BLAH 1 con #if BLAH etc...

88voto

Roddy Points 32503

Ma première réaction a été #ifdef bien sûr. mais je pense que #if présente en fait des avantages considérables à cet égard - voici pourquoi :

Tout d'abord, vous pouvez utiliser DEBUG_ENABLED dans le préprocesseur y des tests compilés. Exemple - Souvent, je veux des délais d'attente plus longs lorsque le débogage est activé. #if je peux écrire ceci

  DoSomethingSlowWithTimeout(DEBUG_ENABLED? 5000 : 1000);

... au lieu de ...

#ifdef DEBUG_MODE
  DoSomethingSlowWithTimeout(5000);
#else
  DoSomethingSlowWithTimeout(1000);
#endif

Deuxièmement, vous êtes dans une meilleure position si vous voulez migrer d'un système de gestion de l'information à un autre. #define à une constante globale. #define sont généralement désapprouvés par la plupart des programmeurs C++.

Et, troisièmement, vous dites qu'il y a une division dans votre équipe. A mon avis, cela signifie que différents membres ont déjà adopté des approches différentes, et que vous devez standardiser. En décidant que #if est le choix préféré signifie que le code utilisant #ifdef compilera -et exécutera- même si DEBUG_ENABLED est fausse. Et c'est beaucoup Il est plus facile de retrouver et de supprimer une sortie de débogage qui est produite alors qu'elle ne devrait pas l'être que l'inverse.

Oh, et un petit point de lisibilité. Vous devriez pouvoir utiliser true/false plutôt que 0/1 dans votre fichier #define et comme la valeur est un seul token lexical, c'est la seule fois où vous n'avez pas besoin de parenthèses autour.

#define DEBUG_ENABLED true

au lieu de

#define DEBUG_ENABLED (1)

0 votes

La constante pourrait ne pas être utilisée pour activer/désactiver le débogage, donc déclencher un #ifdef avec un #define à 0 pourrait ne pas être si bénin. Quant aux true/false, ils ont été ajoutés en C99 et n'existent pas en C89/C90.

0 votes

Micheal : Il/elle préconisait contre l'utilisation de #ifdef ? !

1 votes

...bon point sur le vrai / faux - d'autant plus que notre plateforme embarquée ne définit pas réellement les bools !

58voto

R.. Points 93718

Ils sont tous les deux hideux. A la place, fais ça :

#ifdef DEBUG
#define D(x) do { x } while(0)
#else
#define D(x) do { } while(0)
#endif

Ensuite, chaque fois que vous avez besoin de code de débogage, mettez-le à l'intérieur de D(); . Et votre programme n'est pas pollué par des labyrinthes hideux de #ifdef .

7 votes

@MatthieuM. En fait, je pense que la version originale était très bien. Le point-virgule serait interprété comme une déclaration vide. Cependant, l'oubli du point-virgule pourrait la rendre dangereuse.

38voto

Terence Simpson Points 976

#ifdef vérifie juste si un jeton est défini, étant donné que

#define FOO 0

puis

#ifdef FOO // is true
#if FOO // is false, because it evaluates to "#if 0"

23voto

Brent Priddy Points 2889

Nous avons rencontré ce même problème dans plusieurs fichiers et il y a toujours le problème des personnes qui oublient d'inclure un fichier "features flag" (avec un codebase de > 41 000 fichiers, c'est facile à faire).

Si vous aviez feature.h :

#ifndef FEATURE_H
#define FEATURE_H

// turn on cool new feature
#define COOL_FEATURE 1

#endif // FEATURE_H

Mais vous avez oublié d'inclure le fichier d'en-tête dans file.cpp :

#if COOL_FEATURE
    // definitely awesome stuff here...
#endif

Alors vous avez un problème, le compilateur interprète COOL_FEATURE étant indéfini comme un "faux" dans ce cas et ne parvient pas à inclure le code. Oui, gcc supporte un drapeau qui provoque une erreur pour les macros indéfinies... mais la plupart des codes tiers définissent ou ne définissent pas les caractéristiques, ce qui ne serait pas très portable.

Nous avons adopté un moyen portable de corriger ce cas et de tester l'état d'une fonctionnalité : les macros de fonction.

si vous avez changé le feature.h ci-dessus en :

#ifndef FEATURE_H
#define FEATURE_H

// turn on cool new feature
#define COOL_FEATURE() 1

#endif // FEATURE_H

Mais vous avez encore oublié d'inclure le fichier d'en-tête dans file.cpp :

#if COOL_FEATURE()
    // definitely awseome stuff here...
#endif

Le préprocesseur aurait fait une erreur à cause de l'utilisation d'une macro de fonction non définie.

15voto

Derek Park Points 25025

Je pense que c'est entièrement une question de style. Aucun n'a vraiment d'avantage évident sur l'autre.

La cohérence est plus importante que n'importe quel choix particulier. Je vous recommande donc de vous réunir avec votre équipe, de choisir un style et de vous y tenir.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X