Boucle en C/C++
Il y a plusieurs possibilités de faire une boucle sans fin, voici quelques je choisirais:
for(;;) {}
while(1) {}
/while(true) {}
do {} while(1)
/do {} while(true)
Est-il une certaine forme qui l'on doit choisir? Et ne les compilateurs modernes de faire une différence entre le milieu et la dernière déclaration ou fait réaliser que c'est une boucle sans fin et ignore la vérification de la partie entièrement?
Edit: comme il a été mentionné que j'avais oublié goto
, mais cela a été fait en dehors de la raison que je ne l'aime pas comme un commandement à tous.
Edit2: j'ai fait un grep sur les versions les plus récentes prises de kernel.org. Je ne me semble que rien n'a vraiment changé au fil du temps (dans le Noyau au moins)
- Je crois que vous avez oublié
endless: GOTO endless;
- Je pense que vous devriez choisir l'option qui rend le code lisible assez comme while (true) {}
- Nope, ce n'est pas une boucle sans fin, il en résulte un dépassement de capacité.
- Une "pile" de débordement. Hein??? Eeh?
- Vous avez oublié le GOTO possibilité.
- Ce lien n'est pas seulement pour C#, il contient simplement non-sens subjectif avec tout le monde hautement ses opinions personnelles.
- Vous pouvez également faire un appel récursif à la queue-appel (en supposant que votre compilateur ne la queue-appel d'optimisation). c'est à dire
void loop() { ...; loop(); }
. - Cela a déjà été posée ici: stackoverflow.com/questions/224138/infinite-loops-top-or-bottom
- il a également été demandé sur les programmeurs.stackexchange si je me souviens bien. Qui est à droite, comme de l'omi, c'est plutôt une opinion fondée.
- Personnellement, j'essaie d'éviter cette construction, et vient de mettre la rupture condition dans le contrôle de l'énoncé où il est censé aller. Si je ne peux pas obtenir autour d'elle, je vais utiliser
while(true)
bien. - il n'a jamais ignore la vérification de la partie, sauf si elle est programmmed à faire, ou que quelque chose va mal.
- La plupart des réponses ici miss la subtilité qu'il n'est généralement pas vraiment une boucle sans fin qui a été écrit, simplement celui dont les conditions de sortie ne sont pas testés au le haut ou le bas du corps de la boucle, mais dans le milieu quelque part (ce qui en soi, pour une bonne raison, est généralement considérée comme quelque chose à éviter). Ainsi, tout texte qui implique 'forever' est au moins un abus de langage, même si la plupart des programmeurs savent que "pour toujours" ne veut pas dire pour toujours.
- Je propose #define jamais, alors que(1) Le problème est que ce n'est pas vraiment sans fin, il va finir sur les signaux/sous-système étant terminé. J'ai besoin d'un meilleur nom pour elle... until_subsystem_terminates n'est pas aussi attrayant.
- Bien que certainement une possibilité, si le sentiment que les macros sont une manière horrible ti atteindre le but que les gens ont en fait à la recherche de la définition de la macro afin de le comprendre.
- simple grep sur linux 4.10.10 sources du noyau: 'for(;;)' - 57 occurrences; 'while(true)' - 1; 'while(1)' - 82
- C'est très intéressant. Je me demande comment ces chiffres ont évolué au fil du temps.
- peut 'grep -R" et kernel.org être avec vous 🙂
- J'ai ajouté un graphique à ce sujet. Pour quiconque s'intéresse aussi à elle.
- Aucun d'entre eux sont garantis sans fin les boucles en C++. Choisissez votre langue, le C et le C++ sont des langues différentes!
Vous devez vous connecter pour publier un commentaire.
Le problème avec cette question, c'est que vous aurez beaucoup subjective des réponses que simplement "je préfère cette...". Au lieu de faire de telles inutile déclarations, je vais essayer de répondre à cette question avec des faits et des références plutôt que des opinions personnelles.
Par l'expérience, nous pouvons probablement commencer par l'exclusion de l', tandis que les solutions de rechange (et le goto), car ils ne sont pas couramment utilisés. Je ne m'en souviens jamais de les voir en live le code de production, écrits par des professionnels.
La
while(1)
,while(true)
etfor(;;)
sont les 3 différentes versions répandues dans le code réel. Bien entendu, elles sont complètement équivalentes et les résultats dans le même code machine.for(;;)
C'est l'original, exemple canonique d'une éternelle boucle. Dans l'antiquité, au C de la bible Le Langage de Programmation C par Kernighan et Ritchie, on peut lire que:
K&R 2e ed 3.5:
Pendant un long moment (mais pas toujours), ce livre a été considéré comme canon et la définition même de la langue. Depuis K&R décidé de montrer un exemple de
for(;;)
, cela aurait été considéré comme la forme la plus correcte, au moins jusqu'au C de la normalisation en 1990.Cependant, K&R eux-mêmes déjà dit que c'était une question de préférence.
Et aujourd'hui, K&R est un très discutable source pour l'utiliser comme canonique de C de référence. Non seulement est-elle dépassée à plusieurs reprises (pas de répondre C99, ni C11), il prêche pratiques de programmation qui sont souvent considérés comme mauvais ou manifestement dangereux moderne C programmation.
Mais en dépit de K&R étant une source douteuse, cet aspect historique semble être l'argument le plus fort en faveur de la
for(;;)
.L'argument contre la
for(;;)
boucle, c'est qu'il est quelque peu obscure et illisible. Pour comprendre ce que fait le code, vous devez connaître la règle suivante de la norme:ISO 9899:2011 6.8.5.3:
/--/
Fondée sur ce texte de la norme, je pense que la plupart seront d'accord que ce n'est pas seulement obscur, c'est subtil ainsi, depuis la 1ère et la 3ème partie de la boucle sont traités différemment que les 2ème, quand il est omis.
while(1)
C'est soi-disant une forme plus lisible que
for(;;)
. Cependant, il repose sur un autre obscure, bien que le bien-connu de la règle, à savoir que C traite de tous les non-zéro expressions booléennes vrai logique. Chaque programmeur C est conscient de ce que, donc, il n'est probablement pas un gros problème.Il y a un gros problème pratique avec ce formulaire, à savoir que les compilateurs ont tendance à donner un avertissement: "la condition est toujours vraie" ou similaire. C'est un bon avertissement, du genre de ceux qui vous ne voulez vraiment pas à désactiver, parce que c'est utile pour trouver les bugs divers. Par exemple, un bug comme
while(i = 1)
, lorsque le programmeur avait l'intention d'écrirewhile(i == 1)
.Aussi, statique externe code analyseurs sont susceptibles de se lamenter à propos de "condition est toujours vraie".
while(true)
De faire
while(1)
encore plus lisible, certains utilisentwhile(true)
à la place. Le consensus parmi les programmeurs semblent être que c'est plus lisible.Cependant, cette forme a le même problème que
while(1)
, comme décrit ci-dessus: "la condition est toujours vraie" mises en garde.Quand il s'agit de C, cette forme a un autre inconvénient, à savoir qu'il utilise la macro
true
de stdbool.h. Afin de rendre cette compilation, nous avons besoin d'inclure un fichier d'en-tête, qui peut ou peut ne pas être gênant. En C++, ce n'est pas un problème, puisquebool
existe aussi un type de données primitif ettrue
est un langage de mots clés.Encore un autre inconvénient de cette forme est qu'il utilise du C99 type bool, qui est uniquement disponible sur les compilateurs modernes et pas rétro-compatible. Encore une fois, ce n'est qu'une question en C et pas en C++.
Donc le formulaire à utiliser? Ni semble parfait. Il est, comme le K&R déjà dit dans les âges sombres, une question de préférence personnelle.
Personnellement, j'utilise toujours
for(;;)
juste pour éviter que le compilateur/analyser les avertissements fréquemment générées par les autres formes. Mais le plus important peut-être à cause de cela:Si même un C débutant sait que
for(;;)
signifie une éternelle boucle, alors qui êtes-vous essayer de rendre le code plus lisible pour?Je suppose que c'est ce que tout ça se résume à de la. Si vous vous trouvez à essayer de faire de votre code source lisible pour les non-programmeurs, qui ne connaissent même pas les éléments fondamentaux du langage de programmation, alors vous êtes seulement de perdre du temps. Ils ne devraient pas être la lecture de votre code.
Et depuis tout le monde qui devrait être la lecture de votre code sait déjà ce
for(;;)
moyens, il n'y a aucun point en le rendant plus lisible, il est déjà aussi lisible qu'il obtient.while(true)
ne sont pas valide en C++. Je vais modifier le post.do-while(1)
pas être utilisés dans le code, mais il devient difficile de trouver une source à citer pour que.#define forever for (;;)
peut augmenter la lisibilité. Je pense que je l'ai vu une fois ou deux fois.for(;;)
est "pour toujours", donc dans un sens, c'est plus lisible quewhile(true)
.while(true)
ouwhile(1)
, même au niveau d'alerte 4. Il y a un autre avertissement surwhile(i = 1)
: "l'affectation dans une expression conditionnelle"C'est très subjectif. J'écris ceci:
Parce que son intention est très claire et il est également lisible: vous le regardez et vous savoir boucle infinie est destiné.
On pourrait dire
for(;;)
est également clair. Mais je dirais que, en raison de son syntaxe alambiquée, cette option nécessite connaissances supplémentaires pour arriver à la conclusion que c'est une boucle infinie, il est donc relativement moins clair. Je dirais même qu'il y a plus nombre de programmeurs qui ne savent pas cefor(;;)
n' (même si ils savent que d'habitudefor
de la boucle), mais presque tous les programmeurs qui saitwhile
la boucle immédiatement comprendre cewhile(true)
n'.Pour moi, l'écriture
for(;;)
pour signifier boucle infinie, c'est comme l'écriturewhile()
pour signifier boucle infinie — alors que l'ancien fonctionne, ce dernier n'a PAS. Dans le premier cas, vide condition s'avère êtretrue
implicitement, mais dans le second cas, c'est une erreur! Je personnellement n'aimais pas ça.Maintenant
while(1)
est également là dans la compétition. Je voudrais poser la question: pourquoiwhile(1)
? Pourquoi ne paswhile(2)
,while(3)
ouwhile(0.1)
? Eh bien, tout ce que vous écrivez, vous fait direwhile(true)
— si oui, pourquoi ne pas l'écrire à la place?En C (si jamais je écrire), je serais probablement écrire ceci:
Tout
while(2)
,while(3)
etwhile(0.1)
serait tout aussi logique. Mais juste pour être conforme avec d'autres programmeurs C, je voudrais écrirewhile(1)
, parce que beaucoup de programmeurs C écrire cela et je ne trouve aucune raison de s'écarter de la norme.for(;;)
est relativement moins clair >> "for(;;) est très clair, je n'ai pas encore rencontré un autre (expérimenté) programmeur qui ne sait pas qu'il ressemble à une boucle infinie." (a insisté sur la mienne). Pourquoi avez-vous impression le besoin d'écrire "(expérimenté)" dans votre commentaire? Vous écrivez du code pour expérimenté des programmeurs?for(;;)
? Assurément, il est ambigu. Si nous supposons qu'une boucle de tests pour un état d'êtretrue
avant chaque itération, ce que l'on considère viergetrue
oufalse
?for(;;)
?while(true)
pour les 5 dernières années et mon compilateurs (même avec tous les avertissement est activé), ne donne pas d'avertissement. Probablement ce que vous avez dit était vrai il y a quelque temps dans le passé. Je n'écris paswhile(1)
si, parce que je n'ai pas de code en C et en C++, je trouvewhile(true)
mieux.#define true 1
en C?while(true)
est mieux, car c'est littéralement "lisible" en d'autres termes, vous pouvez le lire à haute voix, le prononcer. Et ça sonne comme il en a l'air: "si cela est VRAI"Dans un ultime acte de l'ennui, j'ai en fait écrit quelques versions de ces boucles et compilé avec GCC sur mon mac mini.
l'
while(1){}
etfor(;;) {}
produit les mêmes résultats de montage
alors que le
do{} while(1);
produit similaire mais d'une autre assemblée du codeheres une pour tout/pour la boucle
et la boucle do while
gcc -S -o test1.asm testing.cpp
avec les trois boucles différentes dans des fichiers séparés, et necmp test1.asm test2.asm
, etc. Il semble y avoir aucune différence.Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1 Apple LLVM version 5.0 (clang-500.2.79) (based on LLVM 3.3svn) Target: x86_64-apple-darwin13.0.0 Thread model: posix
par curiosité, u l'esprit de partage ur de la version de gccTout le monde semble comme
while (true)
:https://stackoverflow.com/a/224142/1508519
https://stackoverflow.com/a/1401169/1508519
https://stackoverflow.com/a/1401165/1508519
https://stackoverflow.com/a/1401164/1508519
https://stackoverflow.com/a/1401176/1508519
Selon SLaks, la compilation de la même manière.
Ben Zotto dit aussi qu'il n'a pas d'importance:
En réponse à user1216838, voici ma tentative de reproduire ses résultats.
Voici ma machine:
version de gcc:
Et les fichiers de test:
Les commandes:
La seule différence est la première ligne de, aka le nom de fichier.
De sortie:
Avec
-O3
, la sortie est considérablement plus petit, bien sûr, mais toujours pas de différence.while (true)
.L'idiome conçu dans le langage C (et en a hérité en C++) pour la boucle infinie est
for(;;)
: l'omission d'un formulaire de test. Ledo/while
etwhile
les boucles n'ont pas cette particularité; leurs expressions sont obligatoires.for(;;)
n'exprime pas "en boucle pendant une certaine condition est vraie que ce qui arrive à être toujours vrai". Il exprime la "boucle sans fin". Pas de superflu condition est présente.Par conséquent, la
for(;;)
construire est la canonique boucle sans fin. C'est un fait.Tout ce qui est à gauche de l'avis est de savoir si ou de ne pas écrire les canonique boucle, ou de choisir quelque chose de baroque qui implique des identificateurs supplémentaires et constantes, de construire un superflu expression.
Même si l'expression de test de
while
étaient facultatifs, ce qui n'est pas le cas,while();
serait étrange.while
quoi? En revanche, la réponse à la questionfor
quoi? est: pourquoi, jamais---pour toujours! Comme une blague, certains programmeurs de jours après avoir défini vide macros, afin qu'ils puissent écrirefor(ev;e;r);
.while(true)
est supérieure àwhile(1)
parce qu'au moins, elle n'implique pas de la bidouille que 1 représente la vérité. Cependant,while(true)
n'entrez pas dans C jusqu'à ce que le C99.for(;;)
existe dans toutes les versions de C de revenir à la langue décrite dans le livre de 1978 K&R1, et dans chaque dialecte de C++, et même les langues apparentées. Si vous êtes de codage dans une base de code écrit en C90, vous devez définir votre propretrue
pourwhile (true)
.while(true)
lit mal. Alors que ce est vrai? Nous n'avons pas vraiment envie de voir l'identificateurtrue
dans le code, sauf lorsque nous sommes initialisation des variables booléennes ou de l'affectation à eux.true
n'a pas besoin d'apparaître dans les tests conditionnels. Bon style de codage évite les trucs comme ça:en faveur de:
Pour cette raison
while (0 == 0)
est supérieure àwhile (true)
: elle utilise une réelle condition que les tests de quelque chose, qui se transforme en une phrase: "en boucle pendant que le zéro est égal à zéro." Nous avons besoin d'un prédicat aller bien avec "tout"; le mot "vrai" n'est pas un prédicat, mais l'opérateur relationnel==
est.for(ever;and;ever);
moi-même. C'est peut-être une question de préférence personnelle.:)
#define forever for(;;)
Ils ont probablement compiler en bas à presque le même code machine, donc c'est une question de goût.
Personnellement, j'aurais choisi celui qui est le plus clair (c'est à dire très clairement que c'est censé être une boucle infinie).
Je pencherais vers
while(true){}
.for(;;)
. Voir le gras remarque dans Lundin de réponse: [I[f même un C débutant sait que for(;;) signifie une éternelle boucle, alors qui êtes-vous essayer de rendre le code plus lisible pour?- Je utiliser
for(;/*ever*/;)
.Il est facile à lire et il faut un peu plus de temps pour type (en raison des changements pour les astérisques), ce qui indique que je devrais vraiment être prudent lors de l'utilisation de ce type de boucle. Le texte en vert qui s'affiche dans le conditionnel est également un joli spectacle étrange—une autre indication de cette construction, c'est mal vu, sauf si absolument nécessaire.
forever
est vraiment une éternelle boucle. L'ajout de l' /*jamais*/ ajoute juste un peu plus de lisibilité.Vous pouvez choisir. Sa matière de prédilection. Toutes sont équivalentes.
while(1) {}/while(true){}
est souvent utilisé pour la boucle infinie par les programmeurs.Bien, il ya beaucoup de goût dans celui-ci.
Je pense que les gens à partir d'un C en arrière-plan sont plus susceptibles de préférer for(;;), qui se lit comme "forever". Si son pour travailler, faire ce que les gens du coin, si son pour vous-même, procédez de l'une que vous pouvez plus facilement lire.
Mais dans mon expérience, do { } while (1); n'est presque jamais utilisée.
Je recommanderais
while (1) { }
ouwhile (true) { }
. C'est ce que la plupart des programmeurs d'écrire, et pour des raisons de lisibilité, vous devez suivre le commun des idiomes.(Ok, il y a donc une évidente "citation nécessaire" pour l'allégation au sujet de la plupart des programmeurs. Mais à partir du code que j'ai vu, en C depuis 1984, je crois que c'est vrai.)
Raisonnable compilateur compiler toutes dans le même code, un inconditionnel de sauter, mais je ne serais pas surpris s'il y a quelques déraisonnable compilateurs là, pour l'embarqué ou d'autres systèmes spécialisés.
Tout va pour effectuer la même fonction, et il est vrai qu'à choisir ce que vous préférez..
je pourrais penser "while(1) ou while(true)" est une bonne pratique à utiliser.
Ils sont les mêmes. Mais je suggère que "tout(ture)", qui a la meilleure représentation.
ture
?? Qui ne compile pas!