6
votes

Y a-t-il une différence dans C et C ++ entre utiliser si, sinon si, sinon, ... et à l'aide de commutateur () {cas A: ... cas B: ...}?

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;
}

c

0 commentaires

9 Réponses :


0
votes

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.

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.


0 commentaires

8
votes

Oui, il y a des différences. Le cascade si 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 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.


1 commentaires

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 et -fguess-branche-probabilité . 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 n'entraînera pas une table de saut si les valeurs sont trop clairsemées.



1
votes

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.

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.

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 >

Mais les réponses courtes courtes sont oui. ils seront très probablement différents.


0 commentaires

6
votes

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: xxx

pourrait devenir (pseudocode): xxx


1 commentaires

Avec si S, dans certaines circonstances, le compilateur peut optimiser le si 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.



0
votes

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.


0 commentaires

0
votes

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.


0 commentaires


0
votes

+1 pour la réponse de David Thomley, car je trouve vraiment cela le plus complet.

Une chose importante est manquante, c'est-à-dire que case doit être des expressions constantes qui évaluent à l'heure de la compilation. Avec si des deux côtés de la comparaison (si vous réduisez le si instruction à cela) est évalué au moment de l'exécution.


0 commentaires

1
votes

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


0 commentaires