web-dev-qa-db-fra.com

Pourquoi ne définir une macro que si elle n'est pas déjà définie?

Partout dans notre base de code C, je vois chaque macro définie de la manière suivante:

#ifndef BEEPTRIM_PITCH_RATE_DEGPS
#define BEEPTRIM_PITCH_RATE_DEGPS                   0.2f
#endif

#ifndef BEEPTRIM_ROLL_RATE_DEGPS
#define BEEPTRIM_ROLL_RATE_DEGPS                    0.2f
#endif

#ifndef FORCETRIMRELEASE_HOLD_TIME_MS
#define FORCETRIMRELEASE_HOLD_TIME_MS               1000.0f
#endif

#ifndef TRIMSYSTEM_SHEARPIN_BREAKINGFORCE_LBS
#define TRIMSYSTEM_SHEARPIN_BREAKINGFORCE_LBS       50.0f
#endif

Quelle est la justification de ces contrôles de définition au lieu de simplement définir les macros?

#define BEEPTRIM_PITCH_RATE_DEGPS                   0.2f
#define BEEPTRIM_ROLL_RATE_DEGPS                    0.2f
#define FORCETRIMRELEASE_HOLD_TIME_MS               1000.0f
#define TRIMSYSTEM_SHEARPIN_BREAKINGFORCE_LBS       50.0f

Je ne trouve cette pratique expliquée nulle part sur le Web.

92
Trevor Hickey

Cela vous permet de remplacer les macros lors de la compilation:

gcc -DMACRONAME=value

Les définitions du fichier d'en-tête sont utilisées par défaut.

138
Barmar

Comme je l'ai dit dans le commentaire, imaginez cette situation:

foo.h

#define FOO  4

defs.h

#ifndef FOO
#define FOO 6
#endif

#ifndef BAR
#define BAR 4
#endif

bar.c

#include "foo.h"
#include "defs.h"

#include <stdio.h>

int main(void)
{
    printf("%d%d", FOO, BAR);
    return 0;
}

Imprime 44.

Cependant, si le ifndef conditionnel n'était pas là, le résultat serait des avertissements de compilation de la redéfinition MACRO et il affichera 64.

$ gcc -o bar bar.c
In file included from bar.c:2:0:
defs.h:1:0: warning: "FOO" redefined [enabled by default]
 #define FOO 6
 ^
In file included from bar.c:1:0:
foo.h:1:0: note: this is the location of the previous definition
 #define FOO 4
 ^
51
Enzo Ferber

Je ne connais pas le contexte mais cela peut être utilisé pour donner à l'utilisateur la possibilité de remplacer les valeurs définies par ces définitions de macro. Si l'utilisateur définit explicitement une valeur différente pour l'une de ces macros, elle sera utilisée à la place des valeurs utilisées ici.

Par exemple, dans g ++, vous pouvez utiliser le -D drapeau pendant la compilation pour passer une valeur à une macro.

17
Ivaylo Strandjev

Ceci est fait pour que l'utilisateur du fichier d'en-tête puisse remplacer les définitions de son code ou de l'indicateur -D du compilateur.

14
Arkadiy

Tout projet C réside sur plusieurs fichiers source. Lorsque vous travaillez sur un seul fichier source, les vérifications semblent (et en fait) ne servent à rien, mais lorsque vous travaillez sur un grand projet C, il est recommandé de vérifier les définitions existantes avant de définir une constante. L'idée est simple: vous avez besoin de la constante dans ce fichier source spécifique, mais elle peut avoir déjà été définie dans un autre.

7
George

Vous pourriez penser à un framework/bibliothèque qui donne à l'utilisateur un préréglage par défaut qui permet à l'utilisateur de le compiler et de travailler dessus. Ces définitions sont réparties dans différents fichiers et l'utilisateur final est conseillé d'inclure son fichier config.h où il peut configurer ses valeurs. Si l'utilisateur a oublié certains définir le système peut continuer à fonctionner en raison du préréglage.

2
LPs

En utilisant

#ifndef BEEPTRIM_PITCH_RATE_DEGPS
#define BEEPTRIM_PITCH_RATE_DEGPS                   0.2f
#endif

permet à l'utilisateur de définir la valeur de la macro en utilisant l'argument de ligne de commande (dans gcc/clang/VS) -DBEEPTRIM_PITCH_RATE_DEGPS=0.3f.

Il y a une autre raison importante. C'est une erreur de redéfinir une macro de préprocesseur différemment. Voir cette réponse à une autre SO question . Sans le #ifndef vérifier, le compilateur devrait produire une erreur si -DBEEPTRIM_PITCH_RATE_DEGPS=0.3f est utilisé comme argument de ligne de commande dans l'appel du compilateur.

1
R Sahu