Est-il un moyen de vérifier une macro est définie et elle est égale à une certaine valeur en même temps
J'utilise régulièrement l'objet-comme les macros du préprocesseur comme booléenne drapeaux dans C code pour allumer et éteindre les sections de code.
Par exemple
#define DEBUG_PRINT 1
Et de l'utiliser ensuite comme
#if(DEBUG_PRINT == 1)
printf("%s", "Testing");
#endif
Cependant, il s'agit d'un problème si le fichier d'en-tête qui contient le #define
est oublié pour être inclus dans le code source. Depuis la macro n'est pas déclaré, le préprocesseur la traite comme si elle est égale à 0, et le #if
déclaration ne s'exécute.
Lorsque le fichier d'en-tête est oublié pour être inclus, non prévu, unruly comportement peut se produire.
Idéalement, je voudrais être capable à la fois de vérifier qu'une macro est définie, et vérifiez qu'il est égal à une certaine valeur, dans une ligne. Si elle n'est pas définie, le préprocesseur renvoie une erreur (ou avertissement).
Je suis à la recherche de quelque chose le long des lignes de:
#if-def-and-true-else-throw-error(DEBUG_PRINT)
...
#endif
C'est comme une combinaison de #ifdef
et #if
, et si elle n'existe pas, utilise #error
.
J'ai exploré quelques pistes, toutefois, les directives de préprocesseur ne peut pas être utilisé à l'intérieur d'un #define
bloc, et autant que je sache, il n'est pas de préprocesseur option pour générer des erreurs/avertissements si une macro n'est pas définie lorsque utilisé à l'intérieur d'un #if
déclaration.
La droite. Alors ce que vous voulez est d'envelopper votre
print
fonction dans une macro ou une autre fonction, plutôt que d'habillage à l'ensemble de l'appel d'emplacements. Ensuite, vous pouvez consolider l'erreur de génération de code dans un seul endroit plutôt que d'essayer de le saupoudrer sur votre projet.Vous pouvez tout aussi facilement oublier d'utiliser
#if-def-and-true-else-throw-error(DEBUG_PRINT)
au lieu de #if DEBUG_PRINT == 1
, de sorte que même si cette fonction existait, il ne serait pas obtenir quelque chose d'utile.Si vous avez défini PrintDebug dans le fichier d'en-tête, qui est l'endroit logique pour elle, alors le code ne compile pas si le fichier d'en-tête n'est pas inclus.
gcc
dispose d'une option (-Wundef
) pour générer un message d'avertissement lorsqu'un non défini identifiant est évalué dans un #if
directive.OriginalL'auteur gbmhunter | 2013-06-18
Vous devez vous connecter pour publier un commentaire.
Cela peut ne pas fonctionner pour le cas général (je ne pense pas qu'il y a une solution générale à ce que vous demandez), mais pour votre exemple, vous pourriez envisager de modifier cette séquence de code:
:
C'est pas plus bavard et ne pourra pas compiler si
DEBUG_PRINT
n'est pas défini ou si elle est définie à être quelque chose qui ne peut pas être comparé avec1
.oui dans ce cas
if
déclaration elle-même n'est pas inclus lorsque le DÉBOGAGE est défini soit comme0
ou1
, lorsqu'il n'est pas défini identificateur non déclaré est levée. Cant affecter les performances de cette façon. Vérifié avec linux/gcc 4.7.2.Cant affecter les performances de cette façon." -- Bien sûr, il peut. Si elle va, pour une mise en œuvre et de définir des options, c'est une autre affaire. "Vérifié avec linux/gcc 4.7.2." - Vous ne pouvez pas vérifier les allégations générales avec une anecdote.
Si votre compilateur n'est pas éliminer la
if
test pour une simple comparaison de deux entiers littéraux au moment de la compilation (au moins pour un non-debug), alors vous voudrez peut-être chercher à l'autre de la chaîne. Presque tous les compilateurs éluder le test (et de la déclaration, si le test renvoie la valeur false) dans le générés exécution de code tant qu'un certain niveau d'optimisation est activée.OriginalL'auteur Michael Burr
Il ne peut pas être une erreur, car la norme spécifie que le comportement est légal. À partir de la section 6.10.1/3 de la norme ISO C99 standard:
Comme Jim Balter notes dans les commentaires ci-dessous, cependant, certains compilateurs (comme gcc) peut émettre des avertissements à ce sujet. Toutefois, étant donné le comportement de substitution
0
non encore comptabilisés préprocesseur jetons est légal (et dans de nombreux cas souhaitable), je m'attends que l'activation de ces mises en garde, dans la pratique, permettrait de générer une quantité importante de bruit.Il n'y a pas moyen de faire exactement ce que vous voulez. Si vous souhaitez générer une compilation à l'échec si la macro n'est pas défini, vous devrez le faire explicitement
pour chaque fichier source qui s'en soucie. Sinon, vous pouvez convertir votre macro à une fonction-comme macro et éviter d'utiliser
#if
. Par exemple, vous pouvez définir unDEBUG_PRINT
macro qui se développe à uneprintf
appel pour les versions de débogage, mais se développe à rien pour les non-debug. Tout fichier qui néglige d'inclure l'en-tête de la définition de la macro puis de ne pas compiler.Un excellent point. J'ai modifié ma réponse.
devnull mentionné -Wundef dans les commentaires ci-dessus; j'ai juste répété ici. "et dans de nombreux cas, souhaitable" -- je pense que c'est plutôt la mauvaise programmation de la pratique. "Je m'attends que l'activation de ces mises en garde, dans la pratique, permettrait de générer une quantité importante de bruit." -- Essayez et vous verrez ... vous êtes plus susceptibles d'attraper des bugs, je pense.
OriginalL'auteur jamesdlin
Plutôt que d'utiliser DEBUG_PRINT directement dans vos fichiers source, mettre ceci dans le fichier d'en-tête:
Un fichier source qui utilise PrintDebug mais ne pas inclure le fichier d'en-tête échoue à compiler.
Si vous avez besoin d'autres codes que les appels à PrintDebug être établie sur la base de DEBUG_PRINT, envisager l'utilisation de Michael Burr suggestion de l'utilisation de la plaine
if
plutôt que#if
(oui, l'optimiseur va pas générer du code à l'intérieur d'une constante faux test).Edit:
Et vous pouvez généraliser PrintDebug ci-dessus pour inclure ou exclure du code arbitraire tant que vous n'avez pas les virgules qui ressemblent à des macro arguments:
Ensuite, vous pouvez écrire des trucs comme
Vous avez déjà la solution pour que, à laquelle j'ai ajouté comme une modification pendant que vous étiez en ajoutant votre commentaire.
OriginalL'auteur Jim Balter
Oui, vous pouvez vérifier à la fois:
Dans cet exemple, même lorsque
#define DEBUG 0
mais il n'est pas égal à 1, donc rien ne sera imprimé.Vous pouvez faire de même ceci:
Ici si vous
#define DEBUG 0
et puisD(1,2,3)
aussi rien ne sera impriméDOC
OriginalL'auteur Eugen Konkov
Il suffit de créer une macro DEBUG_PRINT qui fait la réelle impression:
Si la macro n'est pas défini, alors vous obtiendrez une erreur de compilation, car le symbole n'est pas reconnu.
OriginalL'auteur Lundin
Ainsi, lorsque "si 0" il va ne rien faire et quand "si 1" il va exécuter la macro définie.
OriginalL'auteur Sam Keith