Je suis intéressé s'il y a une différence sur la perspective C ou C ++ compiler si j'utilise:
switch (value) {
case a:
...
break;
case b:
...
break;
case c:
...
break;
}
9 Réponses :
Un interrupteur doit être compilé à un saut avec une adressage indirecte, tandis qu'une séquence de déclarations si une chaîne de sauts conditionnels sera une chaîne de sauts conditionnels. La première est la durée constante; Bien sûr, vous pouvez mettre des conditions beaucoup plus générales dans un si. p>
Edit: Je devrais mentionner que je ne serais pas surpris si certains compilateurs intelligents sont capables de détecter que toutes les conditions d'une chaîne d'IFS ont une forme simple et convertie en un commutateur. Je ne sais pas s'ils le font, mais vous pouvez toujours décompiler et vérifier. P>
Oui, il y a des différences. Le cascade si code> S garantie l'évaluation des conditions dans l'ordre. L'interrupteur ne garantit qu'une seule évaluation de tout ce qui est utilisé comme paramètre de commutation. Selon le compilateur, le commutateur prend souvent (presque) du temps constant, quelle que soit la branche sélectionnée, alors que le si code> Cascade garantit presque que la première jambe est la plus rapide, la deuxième seconde la plus rapide, et ainsi sur le dernier étant le plus lent. P>
Ce n'est pas tout à fait ce simple. Si la condition n'a pas d'effets secondaires (comme dans l'OP), le compilateur peut réorganiser un si / sinon assez facilement. Par exemple, GCC peut faire cela avec des options telles que -freord-blocks code> et -fguess-branche-probabilité code>. Le compilateur peut également être capable de générer une table de saut d'une cascade si une cascade dans certaines circonstances. Enfin, commutateurs code> n'entraînera pas une table de saut si les valeurs sont trop clairsemées.
Cela dépend de la façon dont le compilateur choisit d'optimiser votre code. L'optimisation de code pour un compilateur est un grand champ. p>
Pour trouver la réponse exacte pour votre compilateur Déterminez comment créer un code d'assemblage avec elle et examiner le code de montage différent qui est écrit dans le fichier. p>
Ceci était déjà fait avec un compilateur et vous pouvez voir les résultats ici.
http://www.eventhelix.com/realtimantra/basics/ctoassemblyTranslation3.htmled/a > p>
Mais les réponses courtes courtes sont oui. ils seront très probablement différents. P>
Il y a une différence - avec Switch'ES, le compilateur peut optimiser l'interrupteur pour utiliser une table de recherche. Cela peut être possible s'il y a beaucoup de valeurs suffisamment proches les unes des autres. Par exemple, cet interrupteur: pourrait devenir (pseudocode): p>
Avec si code> S, dans certaines circonstances, le compilateur peut optimiser le si code> arbre pour utiliser une table de recherche. Ceci est beaucoup moins probable, avec les compilateurs actuels, mais ce n'est pas au-delà de ce que dit la norme.
L'instruction de cas peut être compilée à une "table de saut" qui peut être plus rapide s'il y a des dizaines de cas et que vous exécutez ces millions de fois. P>
Il est possible, si la valeur SELECT est un entier (qu'il doit être en C / C ++), que le compilateur pourrait remplacer le si avec une table de saut. p>
Il y a plusieurs différences, selon la norme. P>
code> peut être évaluée plusieurs fois dans la chaîne si CODE> chaîne, une fois dans l'instruction code> code>. Si évaluant la valeur code> n'a pas d'effets secondaires, cela n'est pas important. Li>
- Le
si code> la chaîne ne permettra pas de cascathrough, tandis que l'instruction SWITCH CODE> sera automchiée sans le BAISE CODE>. LI>.
- the
si code> chaîne permet une comparaison générale, mais l'instruction code> interrupteur code> permet uniquement aux comparaisons d'expressions intégrées constantes. LI>
- L'utilisation de
pause; code> est différent. Il sort de l'instruction code> commutateur code>, mais tout autre. Si vous avez besoin de sortir d'une boucle ou d'une liste code> Switch code> en fonction d'une condition, vous avez besoin du si code> chaîne. Li>
- depuis un interrupteur code> code> fait essentiellement un
goto code> à un cas code> instruction ou défaut: code>, il fonctionnera Dans différents endroits, l'exemple quintessentiel étant Duff's Device . (IIRC, Tom Duff l'a considéré comme un fort argument dans la question de la question de la sculpture, mais il n'était pas sûr de quel côté.) Li>
ol>
donc, si la valeur code> est évalué sans effets secondaires, rupture; code> Les instructions sont utilisées de manière cohérente et uniquement dans le commutateur code> code>, la comparaison est de Des valeurs intégrales constantes, et elle n'est pas utilisée de manière funkoise, le comportement peut être identique. Si les compilateurs utiliseront cette équivalence est une autre question. P>
+1 pour la réponse de David Thomley, car je trouve vraiment cela le plus complet. p>
Une chose importante est manquante, c'est-à-dire que case code> doit être des expressions constantes qui évaluent à l'heure de la compilation. Avec si code> des deux côtés de la comparaison (si vous réduisez le si code> instruction à cela) est évalué au moment de l'exécution. P>
Je suis arrivé au même problème, donc j'ai fait quelques tests, voici quelques résultats obtenus à l'aide de la version 3.4.6 / CENTOS 4
AC et CC Utilisation IFS, mais CC prend la variable de la ligne de commande afin que le compilateur ne connaît pas la valeur de "B" au moment de la compilation. BC utilise le commutateur P>
codes source: p>
AC P>
root@dev2 ~ # gcc a.c -o a -O2;gcc b.c -o b -O2;gcc c.c -o c -O2 root@dev2 ~ # time ./a real 0m0.055s user 0m0.055s sys 0m0.000s root@dev2 ~ # time ./b real 0m0.537s user 0m0.535s sys 0m0.001s root@dev2 ~ # time ./c 10 real 0m0.056s user 0m0.055s sys 0m0.000s