72 votes

Pourquoi on utiliserait MACRO +0 ! = 0

Dans mon code je vois ce motif suivant:

#if SOMETHING_SUPPORTED+0 != 0
...
#endif

Malheureusement, c'est un très vieux code et personne ne sait pourquoi et comment il a commencé. Je pense que cela a commencé en C et il a été lentement transformé en C avec des classes et maintenant, il a tendance à C++

Je ne vois pas d'avantage évident de l'utilisation précédente de construire à la place de la "classique", mais peut-être que je suis absent quelque chose:

#if SOMETHING_SUPPORTED
...
#endif

Savez-vous pourquoi aurait-on utiliser #if MACRO+0 != 0 au lieu de #if MACRO?

70voto

Kaz Points 18072

L'idée ici est que la base de code est très ancienne.

Ce truc existe probablement parce que le code avait été porté à un compilateur avec quelques très vieux préprocesseur qui ne permet pas de traiter undefined macros comme 0 dans préprocesseur #if conditions.

C'est-à-dire, en 1989 en C ANSI, il a été normalisé que si nous avons:

#si foo + bar - xyzzy

la directive est soumis à la macro de remplacement, de sorte que si l' foo, bar ou xyzzy sont des macros, ils sont remplacés. Ensuite, tout en restant identificateurs qui n'ont pas été remplacées sont remplacés par 0. Donc, si foo est défini comme 42, mais bar et xyzzy ne sont pas du tout défini, nous obtenons:

#if 42 + 0 - 0

et non, dire, mauvaise syntaxe:

#if 42 + -

ou de quelque autre problème, comme diagnostic de bar n'est pas définie.

Sur un préprocesseur où undefined macros sont traités comme des flans, #if SOMETHING_SUPPORTED étend à juste #if, qui est alors erronée.

C'est la seule manière dont celui - IDENT+0 astuce permet de tout sens réel. Vous simplement ne voulez pas jamais faire cela que si vous pouvez compter sur prétraitement ISO C conforme.

La raison en est que si SOMETHING_SUPPORTED devrait avoir des valeurs numériques, il est, à tort, fofolle de la définir simplement comme un vide. Idéalement, vous voulez détecter lorsque cela s'est produit et d'arrêter la compilation avec un diagnostic.

Deuxièmement, si vous ne l'appui de cette fofolle d'utilisation, vous voudrez certainement un définies explicitement, mais blanche symbole à se comporter comme si elle avait la valeur 1, et non pas la valeur 0. Sinon, vous êtes en train de créer un piège. Quelqu'un pourrait le faire sur la ligne de commande du compilateur:

 -DSOMETHING_SUPPORTED=$SHELL_VAR  # oops, SHELL_VAR expanded to nothing

ou le code:

 #define SOMETHING_SUPPORTED  /* oops, forgot "1" */

Personne ne va ajouter un #define ou -D pour un symbole avec l'intention de tourner hors de la fonction qu'il contrôle! Le programmeur qui insère un #define SOMETHING_SUPPORTED sans 1 serez surpris par le comportement de

 #if SOMETHING_SUPPORTED+0

qui ignore le matériel qui était destiné à être activé.

C'est pourquoi je soupçonne que quelques programmeurs C la lecture de cet ont jamais vu une telle utilisation, et pourquoi je soupçonne que c'est juste une solution de contournement pour le préprocesseur comportement dont l'effet recherché est de sauter le bloc if SOMETHING_SUPPORTED est manquant. Le fait qu'il établit un "programmeur piège" est juste un effet secondaire de la solution de contournement.

Pour contourner ces un préprocesseur question, sans la création d'un programmeur piège est d'avoir, quelque part plus tôt dans l'unité de traduction, ceci:

#ifndef SOMETHING_SUPPORTED
#define SOMETHING_SUPPORTED 0
#endif

et puis d'ailleurs suffit d'utiliser #if SOMETHING_SUPPORTED. Peut-être que cette approche n'a pas à l'origine programmeur, ou peut-être que programmeur pensé qu' +0 astuce a été soigné, et placé à la valeur de son auto-confinement.

44voto

Matt McNabb Points 14273

#if X+0 != 0 est différent d' #if X dans le cas où l' X est défini à vide (note: ceci est différent du cas de l' X n'est pas définie), par ex.:

#define X

#if X          // error
#if X+0 != 0   // no error; test fails

Il est très fréquent de définir des macros vides: la configuration d'un projet peut générer des courants d'en-tête qui contient un tas de lignes #define USE_FOO, #define USE_BAR d'activer les fonctionnalités que le système prend en charge, et ainsi de suite.

L' != 0 est redondant, le code pourrait avoir juste été #if X+0.


Donc, l'avantage de l'utilisation de #if X+0 , c'est que si X est défini comme vide puis la compilation continue avec le bloc ignorés, plutôt que de déclencher une erreur.

Si c'est une bonne idée est discutable, personnellement j'utiliserais #ifdef booléenne macros comme USE_SOME_FEATURE, et #if pour les macros, où la valeur peut correspondre à un intervalle d'entiers par exemple; et je voudrais voir une erreur si je utiliser accidentellement #if avec quelque chose de défini à vide.

35voto

John Zwinck Points 43636

Nous allons faire un tableau !

La seule différence que nous avons trouvé (grâce à des commentateurs) est donc le cas où X est défini, mais n’a aucune valeur (comme une chaîne vide). Je n’ai jamais vu la `` variante avant.

7voto

EJP Points 113412

C’est une autre façon d’écrire

Le +0 est là pour s’assurer que le résultat est un nombre. Si n’est pas défini il évite l’erreur de syntaxe qui résulterait de le .

Mauvaise qualité des choses, mais ne plaisante pas avec elle sauf si tu dois.

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