2013-06-09 3 views
6

Je n'ai jamais travaillé avec #if, #ifdef, #ifndef, #else, #elif et #endif.Avantages de conditionnel préprocesseur sur les déclarations conditionnelles

En passant en revue certains codes sources, j'ai trouvé une utilisation extensive de ces directives. Est-ce que certaines lectures sur les préprocesseurs conditionnels n'ont pas trouvé d'indice comme en quoi sont-elles différentes des instructions conditionnelles normales. Je me demandais quel est l'avantage de code suivant:

#include<iostream> 
int main() 
{ 
    int i = 0; 

    #if i == 0 
     std::cout<<"This"; 
    #else 
     std::cout<<"That"; 
    #endif 
    return 0; 
} 

sur ceci:

#include<iostream> 
int main() 
{ 
    int i = 0; 

    if (i == 0) 
     std::cout<<"This"; 
    else 
     std::cout<<"That"; 
    return 0; 
} 

Aussi, lorsque à utiliser/non à usage conditionnel préprocesseur?

+1

Pour les démarreurs, 'if' est évalué au moment de l'exécution et' # if' est évalué avant la compilation. – Aiias

+0

http://stackoverflow.com/help/dont-ask – xaxxon

+4

@xaxxon: Pouvez-vous expliquer en quoi ce lien est pertinent? – Blender

Répondre

3

Le préprocesseur conditionnel ne fonctionne pas comme dans votre premier exemple.

Cela fonctionne avec des constantes, vous voyez? Au moment de la compilation, il regarde les différentes conditions et met/omet le code source en fonction.

Par exemple:

#define HAS_COMPARISON 

int main() { 
    #ifdef HAS_COMPARISON 
     int i = 0; 
     if(i == 0) std::cout << "This"; 
     else 
    #else 
     std::cout << "That"; 
    #endif 
} 

Avec l'ensemble define, il la variable i et effectuer la comparaison ... bref, il affichera This. Si vous commentez que define, le bloc entier ne sera pas dans votre programme ce qui signifie qu'il sortira toujours That, sans jamais définir la variable ou faire la comparaison.

C'est l'utilisation la plus courante des définitions de préprocesseur. Vous pouvez également définir des valeurs et les comparer pour avoir un comportement variable avec la même définition, mais c'est un autre problème. Une fois de plus: Le préprocesseur conditionnel est évalué au moment de la compilation, les conditions variables sont évaluées lors de l'exécution.

+0

~ corrigez-moi si je me trompe, c'est comme si ** HAS_COMPARISON ** est mis à 0 avant la compilation puis le compilateur élimine le bloc à l'intérieur _ # else_ & _ # endif_ comme pour _dead code elimination_. – ikis

+0

@iKishore Le * préprocesseur * supprime le code avant que le compilateur le voit, ce qui est important car le code conditionnel ne peut pas compiler/provoquer une erreur lorsque le compilateur le voit (par exemple en raison d'erreurs de type ou de fonctions manquantes). – delnan

+1

@iKishore Non, vous avez raison. Si elle est définie sur N'IMPORTE QUELLE valeur, '# else' est éliminé, tandis que si le' # define' est retiré du code, tout de '# ifdef' à' # else' est éliminé. –

1

La compilation conditionnelle signifie que le code ifdef-ed out n'est jamais réellement dans l'application liée finale. Le simple fait d'utiliser des conditions de langage signifie que les deux branches sont dans le code final, le rendant plus grand et potentiellement plus difficile à tester, etc.

Utilisez #ifdef etc quand vous savez au moment de la compilation ce qui est requis. Les conditions de langue sont utilisées lorsque vous ne savez pas ce dont vous avez besoin avant l'exécution.

1

avantages du préprocesseur est que le code est rejeté. Il n'est pas compilé (ce qui prend du temps) et ne génère pas de code machine qui sera chargé dans le ram. Si la décision est dans une boucle TRÈS serrée, il y a BEAUCOUP de fois, il pourrait y avoir une amélioration de la vitesse. Ne supposez pas que c'est important, sauf si vous le chronométrer. Les préjudices du préprocesseur est que vous devez évidemment connaître la réponse au moment de la compilation. Le code source contient maintenant beaucoup de code qui ne peut jamais être exécuté. Il devient plus difficile de tracer pour un humain parce qu'il est souvent difficile de déterminer ce que ces valeurs de temps de compilation auraient été.

+0

En fait, si la condition est une constante à la compilation (et assez simple que le préprocesseur est une option) le compilateur est généralement capable de déduire cela et de supprimer le code mort s'il est testé avec 'if'. – delnan

+0

Assez vrai. Il est toujours bon de garder à l'esprit à quel point les compilateurs sont intelligents. Les gens écrivent souvent du code déroutant pour essayer d'effectuer une optimisation prématurée, puis réalisent qu'ils ne l'ont pas fait plus rapidement et qu'il est plus difficile à lire/maintenir. – xaxxon

4

L'exemple que vous avez montré ne semble pas utile en raison du manque d'autres informations. Mais voici un exemple que #if est utile.

#if OS == LINUX 
//do something 
#elif OS == SOLARIS 
//do something else 
#else 
// 
#endif 

La clé est que #if est évaluée dans le temps de la compilation, mais if est évalué lorsque le programme est exécuté.

#if BYTE_ORDER == LITTLE_ENDIAN 
//do something 
#else 
//do something else 
#endif 
2

L'utilisation des directives du préprocesseur dans ce cas n'est pas entièrement utile. Mais l'utilisation de ces directives de préprocesseur est utile dans de nombreux autres cas.

Ces directives de préprocesseur peuvent être utilisées pour la compilation conditionnelle. par exemple. Si un programme doit être développé pour plusieurs plates-formes, il est possible de donner des valeurs aux constantes spécifiques à la plate-forme. La modification de ces valeurs de compilation spécifiques à la plate-forme peut se faire alors que le code entier peut être maintenu comme une grande entité.

Ils sont également utiles lors du débogage. Les unités de test peuvent être compilées dans le code et exécutées en utilisant ces compilations conditionnelles pendant le débogage, et elles peuvent être arrêtées de la compilation en utilisant celles-ci.

Questions connexes