Tout le monde est au courant des lettres de Dijkstra à l'éditeur: allez à la déclaration considérée comme nuisible (également ici la transcription .html et ici .pdf) et il y a eu un formidable effort depuis ce temps pour éviter la déclaration goto chaque fois que possible. Bien qu'il soit possible d'utiliser goto pour produire du code tentaculaire incontrôlable, il reste néanmoins dans les langages de programmation modernes . Même la structure de contrôle de continuation avancée de Scheme peut être décrite comme un goto sophistiqué.
Quelles circonstances justifient l'utilisation de goto? Quand est-il préférable d'éviter?
Comme question de suivi: C fournit une paire de fonctions, setjmp et longjmp, qui offrent la possibilité de passer non seulement dans le cadre de pile actuel mais dans n'importe quel cadre appelant. Devraient-ils être considérés aussi dangereux que goto? Plus dangereux?
Dijkstra lui-même regrettait ce titre, dont il n'était pas responsable. À la fin de l' EWD1308 (également ici .pdf), il a écrit:
Enfin une petite histoire pour le disque. En 1968, les communications de l'ACM ont publié un de mes textes sous le titre " La déclaration goto considérée comme nuisible ", qui, dans les années suivantes, serait le plus souvent référencée, malheureusement, souvent, par des auteurs qui n'en avaient pas vu plus que son titre, qui est devenu une pierre angulaire de ma renommée en devenant un modèle: nous verrions toutes sortes d'articles sous le titre "X considéré comme dangereux" pour presque tous les X, y compris un intitulé "Dijkstra considéré comme dangereux". Mais que s'était-il passé? J'avais soumis un document sous le titre " Un cas contre la déclaration goto", qui, afin d'accélérer sa publication, était devenu une" lettre au rédacteur en chef "et, ce faisant, il lui avait donné un nouveau titre de sa propre invention! Le rédacteur en chef était Niklaus Wirth.
Un article classique bien pensé sur ce sujet, à rapprocher de celui de Dijkstra, est la programmation structurée avec go to Statements , de Donald E. Knuth. La lecture permet à la fois de rétablir le contexte et une compréhension non dogmatique du sujet. Dans cet article, l'opinion de Dijkstra sur ce cas est rapportée et est encore plus forte:
Donald E. Knuth: Je crois qu'en présentant un tel point de vue, je ne suis en fait pas en désaccord profond avec les idées de Dijkstra, car il a récemment écrit ce qui suit: "Veuillez ne pas tomber dans le piège de croire que je suis terriblement dogmatique à propos de [la aller à la déclaration]. J'ai le sentiment inconfortable que d'autres en font une religion, comme si les problèmes conceptuels de la programmation pouvaient être résolus par une seule astuce, par une simple forme de discipline de codage! "
la source
goto
.goto
: pirater ensemble des outils de programmation structurés pour implémenter agoto
.Réponses:
Les déclarations suivantes sont des généralisations; bien qu'il soit toujours possible de plaider l'exception, elle ne vaut généralement pas (selon mon expérience et mon humble avis) les risques.
Notes de bas de page ci-dessus:
Concernant le point 2, considérons le code suivant:
Au point "faire quelque chose" dans le code, nous pouvons affirmer avec une confiance élevée qui
a
est supérieure àb
. (Oui, j'ignore la possibilité d'un débordement d'entier non pris au piège. Ne nous enlisons pas un exemple simple.)D'un autre côté, si le code avait lu de cette façon:
La multiplicité des façons d'arriver au label 10 signifie que nous devons travailler beaucoup plus dur pour avoir confiance dans les relations entre
a
etb
à ce moment-là. (En fait, dans le cas général, c'est indécidable!)En ce qui concerne le point 4, toute la notion "d'aller quelque part" dans le code n'est qu'une métaphore. Rien ne va vraiment "nulle part" à l'intérieur du CPU, sauf les électrons et les photons (pour la chaleur perdue). Parfois, nous abandonnons une métaphore pour une autre, plus utile, une. Je me souviens avoir rencontré (il y a quelques décennies!) Une langue où
a été implémenté sur une machine virtuelle en compilant action-1 et action-2 en tant que routines sans paramètres hors ligne, puis en utilisant un seul opcode VM à deux arguments qui a utilisé la valeur booléenne de la condition pour invoquer l'une ou l'autre. Le concept était simplement de «choisir quoi invoquer maintenant» plutôt que «aller ici ou y aller». Encore une fois, juste un changement de métaphore.
la source
true
etfalse
sont de types différents), et chaque branche d'un if / else est fondamentalement un lambda.goto
dans un langage de programmation moderne (Go) stackoverflow.com/a/11065563/3309046 .Un de mes collègues a dit que la seule raison d'utiliser un GOTO était si vous vous programmiez si loin dans un coin que c'est la seule issue. En d'autres termes, une conception appropriée à l'avance et vous n'aurez pas besoin d'utiliser un GOTO plus tard.
Je pensais que cette bande dessinée illustre magnifiquement "Je pourrais restructurer le flux du programme, ou utiliser un petit" GOTO "à la place." Un GOTO est une voie de sortie faible lorsque votre conception est faible. Les vélociraptors s'attaquent aux faibles .
la source
Parfois, il est valide d'utiliser GOTO comme alternative à la gestion des exceptions dans une seule fonction:
Le code COM semble tomber dans ce modèle assez souvent.
la source
Je ne me souviens d'avoir utilisé un goto qu'une seule fois. J'avais une série de cinq boucles comptées imbriquées et je devais pouvoir sortir de la structure entière de l'intérieur tôt en fonction de certaines conditions:
J'aurais pu facilement déclarer une variable de coupure booléenne et l'utiliser dans le cadre du conditionnel pour chaque boucle, mais dans ce cas, j'ai décidé qu'un GOTO était tout aussi pratique et tout aussi lisible.
Aucun vélociraptor ne m'a attaqué.
la source
goto
nous et nous a donné une programmation structurée a également rejeté les premiers retours, pour la même raison. Cela dépend de la lisibilité du code, de la clarté avec laquelle il exprime l'intention du programmeur. Créer une fonction dans un autre but que d'éviter d'utiliser un mot-clé décrié entraîne une mauvaise cohésion: le remède est pire que la maladie.goto
, on peut spécifier explicitement la cible. Avecbreak 5;
, (1) je dois compter les fermetures de boucle pour trouver la destination; et (2) si la structure de la boucle change un jour, il peut très bien nécessiter de changer ce nombre afin de maintenir la destination correcte. Si je veux évitergoto
, le gain devrait être de ne pas avoir à suivre manuellement des trucs comme ça.Nous avons déjà eu cette discussion et je maintiens mon propos .
De plus, je en ai marre des gens qui décrivent des structures linguistiques de niveau supérieur comme «
goto
déguisé » , parce qu'ils ont manifestement pas obtenu le point du tout . Par exemple:C'est un non-sens complet. Chaque structure de contrôle peut être implémentée en termes de
goto
mais cette observation est tout à fait triviale et inutile.goto
n'est pas considéré comme nuisible en raison de ses effets positifs mais en raison de ses conséquences négatives et celles-ci ont été éliminées par une programmation structurée.De même, dire «GOTO est un outil, et comme tous les outils, il peut être utilisé et abusé» est complètement faux. Aucun travailleur de la construction moderne n'utiliserait un rocher et ne dirait qu'il est «un outil». Les roches ont été remplacées par des marteaux.
goto
a été remplacé par des structures de contrôle. Si le travailleur de la construction était coincé dans la nature sans marteau, il utiliserait bien sûr un rocher à la place. Si un programmeur doit utiliser un langage de programmation inférieur qui n'a pas la fonctionnalité X, eh bien, bien sûr, il se peut qu'il doive l'utiliser à lagoto
place. Mais si elle l'utilise ailleurs au lieu de la fonction de langue appropriée, elle n'a clairement pas bien compris la langue et l'utilise à tort. C'est vraiment aussi simple que ça.la source
goto
. Vous avez raison dans la mesure où je n'offre aucun argument contre engoto
soi - je n'avais pas l'intention de le faire - il n'y a donc pas de question à poser.Goto est extrêmement bas sur ma liste de choses à inclure dans un programme juste pour le plaisir. Cela ne veut pas dire que c'est inacceptable.
Goto peut être agréable pour les machines d'état. Une instruction switch dans une boucle est (par ordre d'importance typique): (a) pas réellement représentative du flux de contrôle, (b) moche, (c) potentiellement inefficace selon la langue et le compilateur. Vous finissez donc par écrire une fonction par état et à faire des choses comme "return NEXT_STATE;" qui ressemblent même à goto.
Certes, il est difficile de coder les machines à états de manière à les rendre faciles à comprendre. Cependant, aucune de ces difficultés n'est liée à l'utilisation de goto, et rien de tout cela ne peut être réduit en utilisant des structures de contrôle alternatives. À moins que votre langue n'ait une construction de «machine à états». La mienne non.
Dans les rares occasions où votre algorithme est vraiment plus compréhensible en termes de chemin à travers une séquence de nœuds (états) connectés par un ensemble limité de transitions autorisées (gotos), plutôt que par un flux de contrôle plus spécifique (boucles, conditions, etc.) ), alors cela devrait être explicite dans le code. Et vous devez dessiner un joli diagramme.
setjmp / longjmp peut être utile pour implémenter des exceptions ou des comportements de type exception. Bien qu'elles ne soient pas universellement louées, les exceptions sont généralement considérées comme une structure de contrôle "valide".
setjmp / longjmp sont «plus dangereux» que goto dans le sens où ils sont plus difficiles à utiliser correctement, peu importe de façon compréhensible.
Retirer goto de C ne faciliterait pas l'écriture de bon code en C. En fait, il serait préférable de passer à côté du fait que C est censé être capable d'agir comme un langage assembleur glorifié.
Ce sera ensuite "les pointeurs considérés comme nuisibles", puis "le typage du canard considéré comme nuisible". Alors, qui restera pour vous défendre quand ils viendront vous enlever votre construction de programmation dangereuse? Hein?
la source
Sous Linux: Utilisation de goto In Kernel Code sur Kernel Trap, il y a une discussion avec Linus Torvalds et un "nouveau mec" sur l'utilisation des GOTO dans le code Linux. Il y a de très bons points là-bas et Linus vêtu de cette arrogance habituelle :)
Quelques passages:
-
-
la source
goto cleanup_and_exit
est l'une des rares "bonnes" utilisations de goto à gauche maintenant que nous avonsfor
,while
etif
de gérer notre flux de contrôle. Voir aussi: programmers.stackexchange.com/a/154980En C,
goto
ne fonctionne que dans le cadre de la fonction actuelle, ce qui tend à localiser les éventuels bugs.setjmp
etlongjmp
sont beaucoup plus dangereux, étant non locaux, compliqués et dépendants de la mise en œuvre. En pratique cependant, ils sont trop obscurs et peu courants pour causer de nombreux problèmes.Je crois que le danger de
goto
C est grandement exagéré. N'oubliez pas que lesgoto
arguments originaux remontaient à l'époque des langages comme BASIC à l'ancienne, où les débutants écrivaient du code spaghetti comme ceci:Ici, Linus décrit une utilisation appropriée de
goto
: http://www.kernel.org/doc/Documentation/CodingStyle (chapitre 7).la source
setjmp
/longjmp
n'a été spécifié que lorsqu'ils ont été utilisés comme moyen de sauter à un endroit dans une étendue à partir d'autres endroits dans cette même étendue. Une fois que le contrôle quitte la portée où ilsetjmp
est exécuté, toute tentative d'utilisationlongjmp
sur la structure créée parsetjmp
entraînera un comportement indéfini.GOTO A * 40 + B * 200 + 30
. Il n'est pas difficile de voir comment cela était très pratique et très dangereux.Aujourd'hui, il est difficile de voir grand-chose à propos de la
GOTO
déclaration, car les gens de la "programmation structurée" ont surtout gagné le débat et les langages d'aujourd'hui ont suffisamment de structures de flux de contrôle à éviterGOTO
.Comptez le nombre de
goto
s dans un programme C moderne. Maintenant , ajoutez le nombre debreak
,continue
etreturn
des déclarations. De plus, ajoutez le nombre de fois que vous utilisezif
,else
,while
,switch
oucase
. C'est à peu près combienGOTO
votre programme aurait eu si vous écriviez en FORTRAN ou BASIC en 1968 lorsque Dijkstra a écrit sa lettre.À l'époque, les langages de programmation manquaient de flux de contrôle. Par exemple, dans le Dartmouth BASIC d'origine:
IF
les déclarations n'avaient pasELSE
. Si vous en vouliez un, vous deviez écrire:Même si votre
IF
relevé n'avait pas besoin d'unELSE
, il était toujours limité à une seule ligne, qui consistait généralement en unGOTO
.Il n'y avait pas
DO...LOOP
déclaration. Pour les nonFOR
boucles, vous deviez terminer la boucle par un expliciteGOTO
ouIF...GOTO
revenir au début.Il n'y avait pas
SELECT CASE
. Vous deviez utiliserON...GOTO
.Donc, vous vous êtes retrouvé avec beaucoup de
GOTO
s dans votre programme. Et vous ne pouviez pas dépendre de la restriction deGOTO
s à un seul sous-programme (carGOSUB...RETURN
c'était un concept si faible de sous-programmes), donc cesGOTO
s pouvaient aller n'importe où . De toute évidence, cela rendait le flux de contrôle difficile à suivre.C'est de là que vient l'anti-
GOTO
mouvement.la source
420 if (rare_condition) then 3000
//430 and onward: rest of loop and other main-line code
//3000 [code for rare condition]
//3230 goto 430
. L'écriture de code de cette façon évite toutes les branches ou sauts pris dans le cas de la ligne principale commune, mais cela rend les choses difficiles à suivre. L'évitement des branches dans le code assembleur peut être pire, si certaines branches sont limitées par exemple à +/- 128 octets et n'ont parfois pas de paires complémentaires (par exemple "cjne" existe mais pas "cje").cjne r0,expected_value,first_comp_springboard
/.../cjne r1,unexpected_value,second_comp_fallthrough
// `ajmp second_comp_target` //first_comp_springboard: ajmp first_comp_target
//second_comp_fallthrough: ...
. Ce n'est pas un très bon modèle de codage, mais lorsque des cycles individuels comptent, on fait de telles choses. Bien sûr, dans les années 1960, ces niveaux d'optimisation étaient plus importants qu'aujourd'hui, d'autant plus que les processeurs modernes nécessitent souvent des optimisations étranges, et que les systèmes de compilation juste à temps peuvent être en mesure d'appliquer du code d'optimisation pour les processeurs qui n'existaient pas lorsque le le code en question a été écrit.Go To peut fournir une sorte de remplaçant pour la gestion des exceptions "réelles" dans certains cas. Considérer:
Évidemment, ce code a été simplifié pour prendre moins de place, alors ne vous attardez pas trop sur les détails. Mais considérons une alternative que j'ai vue trop souvent dans le code de production par des codeurs allant à des longueurs absurdes pour éviter d'utiliser goto:
Maintenant fonctionnellement, ce code fait exactement la même chose. En fait, le code généré par le compilateur est presque identique. Cependant, dans le zèle du programmeur pour apaiser Nogoto (le dieu redouté de la réprimande académique), ce programmeur a complètement brisé l'idiome sous-jacent que
while
représente la boucle, et a fait un vrai nombre sur la lisibilité du code. Ce n'est pas mieux.Donc, la morale de l'histoire est que si vous vous retrouvez à recourir à quelque chose de vraiment stupide pour éviter d'utiliser goto, alors ne le faites pas.
la source
break
déclarations se trouvent à l'intérieur d'une structure de contrôle montre clairement ce qu'elles font. Avec l'goto
exemple, la personne qui lit le code doit parcourir le code pour trouver l'étiquette, qui pourrait en théorie se trouver avant la structure de contrôle. Je n'ai pas assez d'expérience avec le C à l'ancienne pour juger que l'un est définitivement meilleur que l'autre, mais il y a des compromis dans les deux cas.break
s soient à l'intérieur d'une boucle indique clairement qu'ils sortent de la boucle . Ce n'est pas "exactement ce qu'ils font", car en réalité, il n'y a pas du tout de boucle! Rien n'y a jamais une chance de se répéter, mais ce n'est pas clair jusqu'à la fin. Le fait que vous ayez une "boucle" qui ne s'exécute jamais plus d'une fois signifie que les structures de contrôle sont abusées. Avec l'goto
exemple, le programmeur peut diregoto error_handler;
. Il est plus explicite et encore moins difficile à suivre. (Ctrl + F, "error_handler:" pour trouver la cible. Essayez de faire cela avec "}".)Donald E. Knuth a répondu à cette question dans le livre "Literate Programming", 1992 CSLI. Dans. 17 il y a un essai " Programmation structurée avec des instructions goto " (PDF). Je pense que l'article pourrait également avoir été publié dans d'autres livres.
L'article décrit la suggestion de Dijkstra et décrit les circonstances dans lesquelles elle est valable. Mais il donne également un certain nombre de contre-exemples (problèmes et algorithmes) qui ne peuvent pas être facilement reproduits en utilisant uniquement des boucles structurées.
L'article contient une description complète du problème, l'historique, des exemples et des contre-exemples.
la source
Goto a jugé utile.
J'ai commencé la programmation en 1975. Pour les programmeurs de l'ère des années 1970, les mots "goto considérés comme nuisibles" indiquaient plus ou moins que de nouveaux langages de programmation avec des structures de contrôle modernes valaient la peine d'être essayés. Nous avons essayé les nouvelles langues. Nous nous sommes rapidement convertis. Nous ne sommes jamais revenus.
Nous ne sommes jamais revenus, mais si vous êtes plus jeune, vous n'y êtes jamais allé.
Maintenant, une expérience dans les anciens langages de programmation peut ne pas être très utile, sauf comme indicateur de l'âge du programmeur. Néanmoins, les jeunes programmeurs n'ont pas cette formation, ils ne comprennent donc plus le message véhiculé par le slogan "goto considéré comme nuisible" à son public cible au moment de son introduction.
Les slogans que l'on ne comprend pas ne sont pas très éclairants. Il vaut probablement mieux oublier de tels slogans. De tels slogans n'aident pas.
Ce slogan particulier, "Goto considéré comme nuisible", a pris sa propre vie.
Ne peut-on pas abuser de goto? Réponse: bien sûr, mais alors quoi? Pratiquement chaque élément de programmation peut être abusé. Les humbles
bool
par exemple, sont abusés plus souvent que certains d'entre nous voudraient le croire.En revanche, je ne me souviens pas avoir rencontré un seul cas réel d'abus de goto depuis 1990.
Le plus gros problème avec goto n'est probablement pas technique mais social. Les programmeurs qui ne savent pas grand-chose semblent parfois penser que déprécier goto les rend intelligents. Vous devrez peut-être satisfaire de tels programmeurs de temps en temps. C'est la vie.
Le pire à propos de goto aujourd'hui, c'est qu'il n'est pas assez utilisé.
la source
Attiré par Jay Ballou ajoutant une réponse, je vais ajouter mes 0,02 £. Si Bruno Ranschaert ne l'avait pas déjà fait, j'aurais mentionné l'article de "Programmation structurée avec instructions GOTO" de Knuth.
Une chose que je n'ai pas vue discutée est le type de code qui, bien que pas exactement commun, a été enseigné dans les manuels de Fortran. Des choses comme la gamme étendue d'une boucle DO et de sous-programmes à code ouvert (rappelez-vous, ce serait Fortran II, ou Fortran IV, ou Fortran 66 - pas Fortran 77 ou 90). Il y a au moins une chance que les détails syntaxiques soient inexacts, mais les concepts doivent être suffisamment précis. Les extraits dans chaque cas sont à l'intérieur d'une seule fonction.
Notez que l'excellent mais daté (et épuisé) livre « The Elements of Programming Style, 2nd Edn '' de Kernighan & Plauger comprend des exemples concrets d'abus de GOTO dans la programmation de manuels de son époque (fin des années 70). Le matériel ci-dessous n'est cependant pas de ce livre.
Plage étendue pour une boucle DO
L'une des raisons de ces absurdités était la bonne carte perforée à l'ancienne. Vous remarquerez peut-être que les étiquettes (bien désordonnées car c'était un style canonique!) Sont dans la colonne 1 (en fait, elles devaient être dans les colonnes 1-5) et le code est dans les colonnes 7-72 (la colonne 6 était la suite colonne marqueur). Les colonnes 73 à 80 recevraient un numéro de séquence, et il y avait des machines qui triaient les jeux de cartes perforées dans l'ordre des numéros de séquence. Si vous aviez votre programme sur des cartes séquencées et que vous deviez ajouter quelques cartes (lignes) au milieu d'une boucle, vous auriez à tout repiquer après ces lignes supplémentaires. Cependant, si vous avez remplacé une carte par le truc GOTO, vous pourriez éviter de reséquencer toutes les cartes - vous venez de ranger les nouvelles cartes à la fin de la routine avec de nouveaux numéros de séquence. Considérez qu'il s'agit de la première tentative d'informatique verte
Oh, vous pourriez également noter que je triche et ne crie pas - Fortran IV a été écrit en majuscules normalement.
Sous-programme à code ouvert
Le GOTO entre les étiquettes 76 et 54 est une version du goto calculé. Si la variable i a la valeur 1, passez à la première étiquette de la liste (123); s'il a la valeur 2, passez à la seconde, et ainsi de suite. Le fragment de 76 au goto calculé est le sous-programme à code ouvert. C'était un morceau de code exécuté un peu comme un sous-programme, mais écrit dans le corps d'une fonction. (Fortran avait également des fonctions de déclaration - qui étaient des fonctions intégrées qui tenaient sur une seule ligne.)
Il y avait des constructions pires que le goto calculé - vous pouviez attribuer des étiquettes aux variables et ensuite utiliser un goto assigné. Googling assigné goto me dit qu'il a été supprimé de Fortran 95. Craquez pour la révolution de la programmation structurée qui pourrait à juste titre avoir commencé en public avec la lettre ou l'article "GOTO Considéré Nocif" de Dijkstra.
Sans une certaine connaissance du genre de choses qui ont été faites à Fortran (et dans d'autres langues, dont la plupart sont à juste titre tombées à l'eau), il est difficile pour nous, nouveaux arrivants, de comprendre l'ampleur du problème auquel Dijkstra était confronté. Heck, je n'ai commencé à programmer que dix ans après la publication de cette lettre (mais j'ai eu le malheur de programmer en Fortran IV pendant un certain temps).
la source
goto
`` à l'état sauvage '', la question Wanted: Working Bose-Hibbard Sort Algorithm montre du code (Algol 60) publié en 1963. La disposition d'origine n'est pas comparable aux normes de codage modernes. Le code clarifié (en retrait) est encore assez impénétrable. Lesgoto
déclarations là - bas rendent (très) difficile la compréhension de ce que fait l'algorithme.Il n'y a rien de tel que GOTO considéré comme nocif .
GOTO est un outil, et comme tous les outils, il peut être utilisé et abusé .
Il y a, cependant, de nombreux outils dans le monde de la programmation qui ont tendance à être abusé plus que d' être utilisé , et GOTO est l' un d'entre eux. le AVEC instruction de Delphi en est une autre.
Personnellement, je n'utilise pas non plus de code typique , mais j'ai eu l'usage étrange de GOTO et WITH qui étaient garantis, et une solution alternative aurait contenu plus de code.
La meilleure solution serait que le compilateur vous avertisse simplement que le mot-clé a été corrompu , et vous devriez remplir quelques directives de pragma autour de l'instruction pour vous débarrasser des avertissements.
C'est comme dire à vos enfants de ne pas courir avec des ciseaux . Les ciseaux ne sont pas mauvais, mais leur utilisation n'est peut-être pas la meilleure façon de garder votre santé.
la source
goto
mot clé a été effacé de C #, le concept de "sauter ici" existe toujours en IL. Une boucle infinie peut facilement être construite sans le mot-clé goto. Si ce manque de garantie que le code appelé reviendra, à votre avis, signifie "incapable de raisonner sur le code", alors je dirais que nous n'avons jamais eu cette capacité.goto
C # n'est pas un vrai "goto" au sens originel du mot. C'est une version beaucoup plus faible qui ne permet que de sauter à l'intérieur d'une fonction. Le sens dans lequel j'utilise "goto" permet de sauter n'importe où dans le processus. Donc, bien que C # ait un mot-clé "goto", il n'a sans doute jamais eu, un vrai goto. Oui, un vrai goto est disponible au niveau IL, de la même manière que quand un langage est compilé en assembleur. Mais le programmeur est protégé de cela, incapable de l'utiliser dans des circonstances normales, donc cela ne compte pas.Cela n'a jamais été le cas, tant que vous pouviez penser par vous-même.
la source
Depuis que j'ai commencé à faire quelques choses dans le noyau Linux, les gotos ne me dérangent pas autant qu'autrefois. Au début, j'étais un peu horrifié de voir qu'ils (les gars du noyau) avaient ajouté des gotos dans mon code. Depuis, je me suis habitué à l'utilisation de gotos, dans certains contextes limités, et je vais maintenant les utiliser de temps en temps moi-même. En règle générale, c'est un goto qui saute à la fin d'une fonction pour effectuer une sorte de nettoyage et de renflouement, plutôt que de dupliquer ce même nettoyage et renflouement à plusieurs endroits de la fonction. Et généralement, ce n'est pas quelque chose d'assez grand pour être transféré à une autre fonction - par exemple, la libération de certaines variables localement (k) malloc'ed est un cas typique.
J'ai écrit du code qui n'utilisait setjmp / longjmp qu'une seule fois. C'était dans un programme de séquenceur de batterie MIDI. La lecture s'est produite dans un processus distinct de toutes les interactions de l'utilisateur, et le processus de lecture a utilisé la mémoire partagée avec le processus d'interface utilisateur pour obtenir les informations limitées dont il avait besoin pour faire la lecture. Lorsque l'utilisateur a voulu arrêter la lecture, le processus de lecture a simplement fait un longjmp "retour au début" pour recommencer, plutôt que quelques déroulements compliqués de l'endroit où il se trouvait quand l'utilisateur voulait qu'il s'arrête. Cela a fonctionné très bien, était simple, et je n'ai jamais eu de problèmes ou de bugs liés à cela dans ce cas.
setjmp / longjmp ont leur place - mais cet endroit est celui que vous ne visiterez probablement pas, mais de temps en temps.
Edit: je viens de regarder le code. C'est en fait siglongjmp () que j'ai utilisé, pas longjmp (pas que ce soit un gros problème, mais j'avais oublié que siglongjmp existait même.)
la source
Si vous écrivez une machine virtuelle en C, il s'avère que l'utilisation de gotos calculés (gcc's) comme ceci:
fonctionne beaucoup plus rapidement que le commutateur conventionnel à l'intérieur d'une boucle.
la source
&&op_inc
ne compile certainement pas, car (la gauche)&
attend une valeur l, mais (la droite)&
donne une valeur r.Parce que
goto
peut être utilisé pour confondre la métaprogrammationGoto
est à la fois une expression de contrôle de haut niveau et de bas niveau , et par conséquent, elle n'a tout simplement pas de modèle de conception approprié adapté à la plupart des problèmes.C'est de bas niveau dans le sens où un goto est une opération primitive qui implémente quelque chose de supérieur comme
while
ouforeach
ou quelque chose.Il est de haut niveau dans le sens où, lorsqu'il est utilisé de certaines manières, il prend du code qui s'exécute dans une séquence claire, de manière ininterrompue, à l'exception des boucles structurées, et il le transforme en morceaux de logique qui sont, avec suffisamment de
goto
s, une capture -Sac de logique en cours de remontage dynamique.Il y a donc un côté prosaïque et un côté mauvais
goto
.Le côté prosaïque est qu'un goto pointant vers le haut peut implémenter une boucle parfaitement raisonnable et un goto pointant vers le bas peut faire un
break
ou parfaitement raisonnablereturn
. Bien sûr, un réelwhile
,break
oureturn
serait beaucoup plus lisible, car le pauvre humain n'aurait pas à simuler l'effet dugoto
pour obtenir une vue d'ensemble. Donc, une mauvaise idée en général.Le mauvais côté implique une routine n'utilisant pas goto pendant un certain temps, une pause ou un retour, mais l'utilisant pour ce qu'on appelle la logique des spaghettis . Dans ce cas, le développeur goto-happy construit des morceaux de code à partir d'un labyrinthe de goto, et la seule façon de le comprendre est de le simuler mentalement dans son ensemble, une tâche terriblement fatigante quand il y a beaucoup de goto. Je veux dire, imaginez la difficulté d'évaluer le code où le
else
n'est pas précisément un inverse duif
, où lesif
s imbriqués pourraient permettre certaines choses qui ont été rejetées par l'extérieurif
, etc., etc.Enfin, pour vraiment couvrir le sujet, il convient de noter que pratiquement toutes les langues anciennes, à l'exception de l'algol, ne faisaient initialement que des déclarations uniques soumises à leurs versions de
if-then-else
. Donc, la seule façon de faire un bloc conditionnel était de legoto
contourner en utilisant un conditionnel inverse. Fou, je sais, mais j'ai lu quelques vieilles spécifications. N'oubliez pas que les premiers ordinateurs ont été programmés en code machine binaire, donc je suppose que n'importe quel type de HLL a été une bouée de sauvetage; Je suppose qu'ils n'étaient pas trop pointilleux sur les fonctionnalités HLL qu'ils avaient.Après avoir dit tout ce que j'avais l'habitude d'en coller un
goto
dans chaque programme, j'ai écrit "juste pour ennuyer les puristes" .la source
Refuser l'utilisation de l'instruction GOTO aux programmeurs revient à dire à un menuisier de ne pas utiliser de marteau car cela pourrait endommager le mur pendant qu'il enfonce un clou. Un vrai programmeur sait comment et quand utiliser un GOTO. J'ai suivi certains de ces soi-disant «programmes structurés». J'ai vu un tel code horrible juste pour éviter d'utiliser un GOTO, que j'ai pu tirer sur le programmeur. Ok, pour défendre l'autre côté, j'ai vu du vrai code spaghetti aussi et encore, ces programmeurs devraient aussi être abattus.
Voici juste un petit exemple de code que j'ai trouvé.
-----------------------OU----------------------
la source
goto
- et sait pourquoi . Éviter une construction de langage tabou parce que $ programming_guru l'a dit, c'est la définition même de la programmation cargo-culte."Dans ce lien http://kerneltrap.org/node/553/2131 "
Ironiquement, l'élimination du goto a introduit un bug: l'appel spinlock a été omis.
la source
Le document original doit être considéré comme "GOTO inconditionnel considéré comme nuisible". Il préconisait en particulier une forme de programmation basée sur des constructions conditionnelles (
if
) et itératives (while
), plutôt que sur le test-and-jump commun au code ancien.goto
est toujours utile dans certaines langues ou circonstances, où aucune structure de contrôle appropriée n'existe.la source
À propos du seul endroit où je suis d'accord Goto pourrait être utilisé est le moment où vous devez traiter les erreurs, et chaque point particulier où une erreur se produit nécessite une gestion particulière.
Par exemple, si vous saisissez des ressources et utilisez des sémaphores ou des mutex, vous devez les saisir dans l'ordre et vous devez toujours les libérer de la manière opposée.
Certains codes nécessitent un modèle très étrange de récupération de ces ressources, et vous ne pouvez pas simplement écrire une structure de contrôle facilement maintenue et comprise pour gérer correctement à la fois la récupération et la libération de ces ressources pour éviter un blocage.
Il est toujours possible de le faire correctement sans goto, mais dans ce cas et quelques autres, Goto est en fait la meilleure solution principalement pour la lisibilité et la maintenabilité.
-Adam
la source
Une utilisation GOTO moderne est par le compilateur C # pour créer des machines d'état pour les énumérateurs définis par return return.
GOTO est quelque chose qui devrait être utilisé par les compilateurs et non par les programmeurs.
la source
goto
. Là où nous pourrions utilisergoto
dans une machine d'état codée à la main pour implémenter un énumérateur, nous pouvons simplement utiliser à layield
place.Jusqu'à ce que C et C ++ (entre autres coupables) aient étiqueté les ruptures et continuent, goto continuera d'avoir un rôle.
la source
Si GOTO lui-même était mauvais, les compilateurs seraient mauvais, car ils génèrent des JMP. Si sauter dans un bloc de code, en particulier après un pointeur, était intrinsèquement mauvais, l'instruction RETurn serait mauvaise. Au contraire, le mal est dans le potentiel d'abus.
Parfois, j'ai dû écrire des applications qui devaient suivre un certain nombre d'objets où chaque objet devait suivre une séquence complexe d'états en réponse à des événements, mais le tout était définitivement monofil. Une séquence typique d'états, si elle est représentée en pseudo-code, serait:
Je suis sûr que ce n'est pas nouveau, mais la façon dont je l'ai géré en C (++) était de définir des macros:
Ensuite (en supposant que l'état est initialement 0), la machine à états structurée ci-dessus se transforme en code structuré:
Avec une variation à ce sujet, il peut y avoir APPEL et RETOUR, donc certaines machines d'état peuvent agir comme des sous-routines d'autres machines d'état.
Est-ce inhabituel? Oui. Faut-il un peu d'apprentissage de la part du responsable? Oui. Cet apprentissage est-il payant? Je le pense. Pourrait-il être fait sans GOTO qui saute en blocs? Nan.
la source
Je l'évite car un collègue / manager remettra sans aucun doute en question son utilisation soit dans une révision de code, soit lorsqu'ils tomberont dessus. Bien que je pense qu'il a des utilisations (le cas de la gestion des erreurs par exemple) - vous rencontrerez un autre développeur qui aura un problème avec lui.
Ça ne vaut pas le coup.
la source
En fait, je me suis retrouvé obligé d'utiliser un goto, car je ne pouvais littéralement pas penser à une meilleure façon (plus rapide) d'écrire ce code:
J'avais un objet complexe et j'avais besoin de faire une opération dessus. Si l'objet était dans un état, alors je pouvais faire une version rapide de l'opération, sinon je devais faire une version lente de l'opération. Le fait était que dans certains cas, au milieu de l'opération lente, il était possible de réaliser que cela aurait pu être fait avec l'opération rapide.
C'était dans un morceau critique de vitesse du code de l'interface utilisateur en temps réel, donc je pense honnêtement qu'un GOTO était justifié ici.
Hugo
la source
Presque toutes les situations où un goto peut être utilisé, vous pouvez faire de même en utilisant d'autres constructions. Goto est de toute façon utilisé par le compilateur.
Personnellement, je ne l'utilise jamais explicitement, je n'en ai jamais besoin.
la source
Une chose que je n'ai vu dans aucune des réponses ici, c'est qu'une solution «goto» est souvent plus efficace qu'une des solutions de programmation structurée souvent mentionnées.
Considérons le cas des boucles imbriquées multiples, où l'utilisation de «goto» au lieu d'un tas de
if(breakVariable)
sections est évidemment plus efficace. La solution "Mettez vos boucles dans une fonction et utilisez return" est souvent totalement déraisonnable. Dans le cas probable où les boucles utilisent des variables locales, vous devez maintenant les passer toutes par le biais de paramètres de fonction, gérant potentiellement des charges de maux de tête supplémentaires qui en découlent.Considérons maintenant le cas de nettoyage, que j'ai moi-même utilisé assez souvent, et qui est si courant qu'il est vraisemblablement responsable de la structure try {} catch {} non disponible dans de nombreuses langues. Le nombre de vérifications et de variables supplémentaires nécessaires pour accomplir la même chose est bien pire que la ou les deux instructions pour effectuer le saut, et encore une fois, la solution de fonction supplémentaire n'est pas du tout une solution. Vous ne pouvez pas me dire que c'est plus gérable ou plus lisible.
Désormais, l'espace de code, l'utilisation de la pile et le temps d'exécution peuvent ne pas être assez importants dans de nombreuses situations pour de nombreux programmeurs, mais lorsque vous êtes dans un environnement intégré avec seulement 2 Ko d'espace de code pour travailler, 50 octets d'instructions supplémentaires pour éviter une définition claire 'goto' est juste risible, et ce n'est pas une situation aussi rare que le croient de nombreux programmeurs de haut niveau.
La déclaration selon laquelle «goto est nuisible» a été très utile pour évoluer vers une programmation structurée, même si elle a toujours été une généralisation excessive. À ce stade, nous l'avons tous suffisamment entendu pour ne pas l'utiliser (comme nous le devrions). Quand c'est évidemment le bon outil pour le travail, nous n'avons pas besoin d'en avoir peur.
la source
Vous pouvez l'utiliser pour interrompre une boucle profondément imbriquée, mais la plupart du temps, votre code peut être refactorisé pour être plus propre sans boucles profondément imbriquées.
la source