28 votes

Y a-t-il un court-circuit logique dans le préprocesseur C?

Les documents gcc pour cpp expliquent la directive #if :

[...] et opérations logiques (&& et ||). Ces deux derniers obéissent aux règles habituelles de court-circuit de la norme C.

Qu'est-ce que ça veut dire? Il n'y a pas d'évaluation des expressions pendant le prétraitement, alors comment les court-circuiter?

26voto

jthill Points 10384

Très simple: undefined macros valeur numérique zéro, et la division par zéro est illégal.

#if FIXEDSIZE && CHUNKSIZE/FIXEDSIZE > 42
#define USE_CELLPOOL
#endif

#if n'évaluer le reste de la ligne comme une constante entière de l'expression. Lien de la documentation commence:

Le " #si la directive permet de tester la valeur d'une expression arithmétique, plutôt que la simple existence d'une macro.

Ce n'est pas un gcc extension, la Norme de la syntaxe pour l' #if est

#ifconstant-expression new-line groupopt.

Le C99 préprocesseur traite toutes les constantes [u]intmax_t.

9voto

Jeffery Thomas Points 12768

Ce dont il est question est && et || opérateurs pour l' #if

#if defined (AAA) || defined (BBB)

Si defined (AAA) est défini, defined (BBB) n'est jamais évaluée.


Mise à JOUR

Il faut donc lancer le calcul va être court-circuitée. Par exemple, si vous créez avec -Wundef à mettre en garde sur l'utilisation de l'indéfini des macros.

#if defined FOO && FOO > 1000
#endif

#if FOO > 1000
#endif

entraînera

thomas:~ jeffery$ gcc foo.c -Wundef
foo.c:4:5: warning: 'FOO' is not defined, evaluates to 0 [-Wundef]
#if FOO > 1000
    ^
1 warning generated.

Donc, la première version ne génère pas mal défini d'avertissement de macro, car FOO > 1000 n'est pas évalué.


VIEILLES RÊVERIES

Cela devient important si la deuxième partie est une macro qui a des effets secondaires. La macro ne serait pas évalué, de sorte que les effets secondaires n'aurait pas lieu.


Pour éviter macro abus je vais vous donner un peu sane exemple

#define FOO
#define IF_WARN(x) _Pragma (#x) 1
#if defined(FOO) || IF_WARN(GCC warning "FOO not defined")
#endif

Maintenant que j'ai construit cet exemple, j'ai un problème. IF_WARN est toujours évalué.

hein, plus de recherche est nécessaire.


Bien foo... maintenant que je l'ai lu à nouveau.

Les Macros. Toutes les macros dans l'expression sont développées avant le calcul de la valeur de l'expression commence.

4voto

haccks Points 33022

Il n'y a pas d'évaluation des expressions lors du pré-traitement, alors comment peut-il être court-circuité?

Oui, il y a l'évaluation de l'expression au cours du prétraitement.

C11: 6.10.1 Conditionnelle de l'inclusion (p4):

Avant l'évaluation, de la macro invocations dans la liste de prétraitement des jetons qui deviendra ...

Dans une note de bas de page 166:

Parce que le contrôle constant de l'expression est évaluée lors de la traduction de la phase 4, tous les identificateurs....

Ces déclarations témoignent clairement qu' il est l'évaluation de l'expression dans le prétraitement. La condition nécessaire est que le contrôle de l'expression doit correspondre à une valeur entière.
L'opérateur && et || obéir à l'habitude de court-circuit règles de la norme C comme indiqué dans GNU doc.

Maintenant exécuter ce programme avec et sans // et de voir le résultat pour voir le court-circuit de comportement:

#include<stdio.h>
#define macro1 1
//#define macro2 1
int main( void )
{
    #if  defined (macro1)  && defined (macro2)
    printf( "Hello!\n" );
    #endif
    printf("World\n"); 
    return 0;
}

3voto

M M. Points 29201

L'évaluation des conditions de macros est une partie (une grande partie) de pré-traitement, de sorte qu'il se produit et de court-circuit est significative. Vous pouvez voir des exemples des autres réponses.

Un conditionnelle est une directive qui demande au préprocesseur pour sélectionner de savoir si ou de ne pas inclure un morceau de code dans le dernier jeton de flux passés au compilateur. Préprocesseur conditionnelles peut test arithmétique expressions, ou si un nom est défini comme une macro, ou les deux simultanément à l'aide de la opérateur défini.

En outre, il peut réduire le temps de compilation. Modifier les évaluations suivantes peuvent accélérer la compilation (depeds sur la mise en œuvre d'un compilateur).

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