Question

Tout le monde est conscient de Dijkstra est Lettres à l'éditeur:allez à la déclaration considéré comme nocif (aussi ici .html la transcription et de la ici .pdf) et il y a eu une formidable poussée depuis ce temps, d'utiliser l'instruction goto chaque fois que possible.Alors qu'il est possible d'utiliser la fonction goto pour produire désuète, tentaculaire code, il reste néanmoins dans langages de programmation modernes.Même les avancées continuation structure de contrôle dans le Régime peut être décrite comme un système sophistiqué de goto.

Ce que les circonstances le justifient l'utilisation de goto?Quand est-il mieux éviter?

Comme une réponse à la question:C fournit une paire de fonctions setjmp et longjmp, qui offrent la possibilité de goto non seulement au sein de l'actuel cadre de la pile, mais dans toute l'appel des cadres.Devraient-ils être considérés comme dangereux que goto?Plus dangereux?


Dijkstra lui-même a regretté que le titre, pour lequel il n'était pas responsable.À la fin de EWD1308 (aussi ici .pdf), il écrit:

Enfin, une courte histoire de l'enregistrement.En 1968, les Communications de l'ACM publié un texte de la mine en vertu de la le titre "L'instruction goto considéré comme nocif"qui dans les dernières années les plus fréquemment citées, malheureusement, cependant, souvent par les auteurs qui avait vu plus que sa le titre, qui est devenu une pierre angulaire de la ma renommée en devenant un modèle:nous serait-voir toutes sortes d'articles sous le titre "X considérées comme nuisibles" pour presque tout X, dont l'un intitulé "Dijkstra considéré comme nocif".Mais ce qui s'était passé?J'avais présenté un papier sous le titre "Une affaire à l'encontre de l'instruction goto"qui, dans l'ordre pour accélérer sa publication, la l'éditeur avait changé dans une "lettre à l'Éditeur", et dans le processus, il a lui a donné un nouveau titre de son propre l'invention!L'éditeur a été Niklaus Wirth.

Bien pensée classique papier sur ce sujet, pour être jumelé à celui de Dijkstra, est La Programmation structurée avec aller à des Déclarations, par Donald E.Knuth.La lecture contribue à rétablir le contexte et non dogmatique de la compréhension de l'objet.Dans ce papier, Dijkstra est d'avis sur ce cas est signalé et est encore plus forte:

Donald E.Knuth: Je crois que, par la présentation d'une telle vue que je ne suis pas en fait en désaccord fortement avec Dijkstra idées, depuis récemment, il a écrit ce qui suit:"S'il vous plaît, ne tombez pas dans le piège de croire que je suis terriblement dogmatical sur [aller à déclaration]. J'ai du mal à l'aise sentiment que les autres font religion, comme si le les problèmes conceptuels de la programmation pourrait être résolu par un seul truc, par un simple formulaire de codage de la discipline!"

Était-ce utile?

La solution

Les énoncés suivants sont des généralisations;alors qu'il est toujours possible d'invoquer une exception, il est habituellement (dans mon expérience et mon humble avis) ne vaut pas les risques.

  1. Sans contrainte d'utiliser des adresses de mémoire (soit GOTO ou raw pointeurs) offre aussi de nombreuses possibilités de faire des erreurs facilement évitables.
  2. Le plus de manières, il y a pour arriver à un "emplacement" dans le code, les moins confiants, on peut être sur ce que l'état du système est à ce point.(Voir ci-dessous).
  3. La programmation structurée à mon humble avis est moins sur "comment éviter les GOTOs" et plus sur la structure du code de correspondre à la structure des données.Par exemple, la répétition d'une structure de données (par ex.tableau, fichier séquentiel, etc.) est naturellement traitées par une répétition de l'unité de code.Après avoir construit des structures (p. ex.tandis que, pour d', jusqu'à ce que, pour chacun, etc.) permet au programmeur pour éviter l'ennui de la répétition du même stéréotypés modèles de code.
  4. Même si le GOTO est de faible niveau de détail de l'implémentation (pas toujours le cas!) il est au-dessous du niveau que le programmeur doit être pensée.Combien de programmeurs équilibrer leur vie personnelle chéquiers en binaire brut?Combien de programmeurs se soucier du secteur sur le disque contient un enregistrement particulier, au lieu de simplement fournir une clé pour un moteur de base de données (et de combien de façons est-ce qui pourrait aller mal si on a vraiment écrit de tous nos programmes en termes de secteurs physiques du disque dur)?

Notes de bas de page ci-dessus:

Concernant le point 2, considérons le code suivant:

a = b + 1
/* do something with a */

À la "faire quelque chose" dans le code, nous pouvons affirmer avec confiance élevé a est plus grand que b.(Oui, je suis en ignorant la possibilité de non interceptée débordement d'entier.Laissez pas embourber un exemple simple.)

D'autre part, si le code avait lu de cette façon:

...
goto 10
...
a = b + 1
10: /* do something with a */
...
goto 10
...

La multiplicité des façons d'obtenir de l'étiquette 10 signifie que nous devons travailler beaucoup plus difficile d'être confiant sur les relations entre a et b à ce point.(En fait, dans le cas général, c'est undecideable!)

Concernant le point 4, la notion de "quelque part" dans le code est juste une métaphore.Rien n'est vraiment "aller" n'importe où à l'intérieur de la CPU à l'exception des électrons et des photons (de la chaleur résiduelle).Parfois nous donner une métaphore pour une autre, plus utile, un.Je me souviens de la rencontre (il y a quelques décennies!) une langue où

if (some condition) {
  action-1
} else {
  action-2
}

a été mis en œuvre sur une machine virtuelle grâce à la compilation de l'action 1 et l'action-2 à l'extérieur de la ligne sans paramètre routines, puis à l'aide d'un seul à deux arguments VM opcode qui a utilisé la valeur booléenne de la condition d'invoquer l'une ou l'autre.Le concept a été tout simplement "choisir ce que pour appeler maintenant" plutôt que de "rendez-vous ici ou là".De nouveau, juste un changement de métaphore.

Autres conseils

XKCD's GOTO Comic

Un collègue m'a dit que la seule raison d'utiliser un GOTO est si vous programmez vous-même jusqu'à présent dans un coin que c'est le seul moyen de sortir.En d'autres mots, le bon design à l'avance et vous n'aurez pas besoin d'utiliser un GOTO plus tard.

Je pensais que cette bande dessinée illustre magnifiquement "j'ai pu restructurer le programme de flux, ou d'en utiliser un peu de "GOTO" à la place." Un GOTO est un faible moyen de sortir quand vous avez une mauvaise conception. Velociraptors proie à la faiblesse de l'.

Parfois, il est valide d'utiliser GOTO comme une alternative à l'exception de manutention dans une seule fonction:

if (f() == false) goto err_cleanup;
if (g() == false) goto err_cleanup;
if (h() == false) goto err_cleanup;

return;

err_cleanup:
...

COM code semble tomber dans ce schéma assez souvent.

Je ne peux que rappeler à l'aide d'un goto à la fois.J'ai eu une série de cinq imbriquée compté boucles et j'ai besoin d'être en mesure de sortir de l'ensemble de la structure de l'intérieur au début en fonction de certaines conditions:

for{
  for{
    for{
      for{
        for{
          if(stuff){
            GOTO ENDOFLOOPS;
          }
        }
      }
    }
  }
}

ENDOFLOOPS:

Je pourrais juste avoir facilement a déclaré un booléen pause variable et l'a utilisé comme une partie de la condition, pour chaque tour de boucle, mais dans ce cas, j'ai décidé d'un GOTO a été aussi pratique et tout aussi lisible.

Pas de velociraptors m'a attaqué.

Nous avons déjà eu ce discussion et je maintiens de mon point de.

En outre, j'en ai marre des gens décrire plus élevé au niveau des structures de la langue comme “goto dans le déguisement” parce qu'ils n'ont manifestement pas eu le point de à tous.Par exemple:

Même les avancées de la continuation de la structure de contrôle dans le Régime peut être décrite comme un système sophistiqué de goto.

C'est un non-sens complet. Chaque structure de contrôle peuvent être mises en œuvre en termes de goto mais cette observation est tout à fait insignifiant 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 ils ont été éliminés par la programmation structurée.

De même, en disant: “GOTO est un outil, et comme tous les outils, il peut être utilisé et abusé” est complètement à côté de la marque.Aucune construction moderne travailleur serait d'utiliser un rocher et à prétendre qu'il “est un outil.” Les roches ont été remplacés par des marteaux. goto a été remplacée par des structures de contrôle.Si le travailleur de la construction ont été bloqués dans la nature sans un marteau, bien sûr, il aurait recours à un rocher au lieu.Si un programmeur doit utiliser un niveau inférieur langage de programmation qui n'a pas de fonction de X, ainsi, bien sûr, elle peut avoir à utiliser goto au lieu de cela.Mais si elle l'utilise n'importe où d'autre à la place de la langue appropriée en fonction, elle a clairement n'a pas compris la langue correctement et l'utilise à tort.C'est vraiment aussi simple que cela.

Goto est extrêmement faible sur ma liste de choses à inclure dans un programme juste pour le plaisir de le faire.Cela ne veut pas dire que c'est inacceptable.

Goto peut être sympa pour les machines d'état.Une instruction switch dans une boucle est (dans l'ordre de la typique d'importance):(a) pas réellement représentative du flux de contrôle, (b) laid, (c) potentiellement inefficace en fonction de la langue et du compilateur.Donc, vous finissez par écrire une fonction par l'état, et de faire des choses comme "retour NEXT_STATE;" qui ressemblent même goto.

Accordé, il est difficile de code de machines d'état d'une manière qui les rendent faciles à comprendre.Cependant, rien de tout cela, la difficulté est de le faire avec l'aide de goto, et aucun ne peut être réduit par l'utilisation alternative des structures de contrôle.À moins que votre langue a un "etat machine" de construire.La mienne n'a pas.

Dans les rares occasions où votre algorithme est vraiment la plus compréhensible en termes d'un chemin à travers une séquence de nœuds (les états) reliés par un ensemble limité de transitions permises (gotos), plutôt que par n'importe quel plus spécifiques de flux de contrôle (boucles, instructions conditionnelles, que sais-je encore), alors que ce devrait être explicite dans le code.Et vous devez dessiner un joli schéma.

setjmp/longjmp peut être sympa pour la mise en œuvre des exceptions ou d'une exception de type de comportement.Alors que pas universellement loué, les exceptions sont généralement considérés comme un "valide" structure de contrôle.

setjmp/longjmp sont "plus dangereux" que goto dans le sens où ils sont plus difficile à utiliser correctement, jamais l'esprit de façon compréhensible.

Il n'y a jamais été, ni ne sera-t-il jamais, de toute langue dans laquelle il est le moins peu difficile d'écrire un mauvais code.-- Donald Knuth.

La prise de goto en C ne serait pas facile à écrire du bon code en C.En fait, il s'agirait plutôt de manquer le point que C est censé pour être capable d'agir comme un être glorifié langage assembleur.

Ensuite, c'est "pointeurs considérés comme nuisibles", puis "duck-typing considéré comme nocif".Alors, qui sera à gauche de vous défendre, quand ils viennent à emporter votre programmation dangereuse de construire?Hein???

Dans Linux:Utilisation de goto Dans le Code du Noyau le Noyau Piège, il y a une discussion avec Linus Torvalds et un "petit nouveau" sur l'utilisation des GOTOs dans le code Linux.Il ya quelques très bons points là-bas et Linus habillé que d'habitude arrogance :)

Certains passages:

Linus:"Non, vous avez été un lavage de cerveau par CS des gens qui pensaient que Niklaus Wirth savaient réellement ce qu'il était parle.Il n'a pas.Il n'a pas avoir une branlant la moindre idée."

-

Linus:"Je pense que les goto sont beaux, et ils sont souvent plus lisible que de grandes quantités d'indentation."

-

Linus:"Bien sûr, dans les langues stupide comme Pascal, où les étiquettes ne peuvent pas être descriptif goto peut être mauvais."

En C, goto fonctionne uniquement dans le cadre de la fonction actuelle, qui tend à localiser les éventuels bugs. setjmp et longjmp sont beaucoup plus dangereux, la non-local, compliquée et dépend de l'implémentation.Dans la pratique, cependant, ils sont trop obscure et rare à cause de nombreux problèmes.

Je crois que le danger de goto C est grandement exagérée.Rappelez-vous que l'original goto arguments a eu lieu dans les jours de langues comme l'ancienne BASE, où les débutants écrire de code spaghetti comme ceci:

3420 IF A > 2 THEN GOTO 1430

Ici Linus décrit une utilisation appropriée de goto: http://www.kernel.org/doc/Documentation/CodingStyle (chapitre 7).

Aujourd'hui, il est difficile de voir la grosse affaire sur les GOTO car, la "programmation structurée" la plupart des gens a gagné le débat et aujourd'hui les langues ont suffisamment de flux de contrôle des structures à éviter GOTO.

Compter le nombre de gotos dans un cadre moderne C programme.Maintenant, ajoutez le nombre de break, continue, et return des déclarations.En outre, ajouter le nombre de fois que vous utilisez if, else, while, switch ou case.C'est à propos de la façon dont beaucoup de GOTOs votre programme aurait eu si vous avez été écrit en FORTRAN ou en BASIC, en 1968, lors de Dijkstra a écrit sa lettre.

Les langages de programmation à l'époque, étaient dépourvues de flux de contrôle.Par exemple, dans l'original, Dartmouth de BASE:

  • IF déclarations avaient pas ELSE.Si vous en voulais un, on devait écrire:

    100 IF NOT condition THEN GOTO 200
    ...stuff to do if condition is true...
    190 GOTO 300
    200 REM else
    ...stuff to do if condition is false...
    300 REM end if
    
  • Même si votre IF la déclaration n'a pas besoin d'un ELSE, il était encore limitée à une seule ligne, qui est en général constitué d'un GOTO.

  • Il n'y a pas de DO...LOOP l'énoncé.Pour les non-FOR les boucles, vous avez eu à la fin de la boucle explicite GOTO ou IF...GOTO retour au début.

  • Il n'y a pas de SELECT CASE.Vous avez eu à utiliser ON...GOTO.

Donc, vous vous retrouviez avec une beaucoup de GOTOs dans votre programme.Et l'on ne pouvait pas compter sur la restriction de GOTOs à l'intérieur d'un seul sous-programme (parce que GOSUB...RETURN était une faiblesse de la notion de sous-programmes), de sorte que ces GOTOs pourrait aller n'importe où.Évidemment, ce qui fait que le contrôle de flux de mal à suivre.

C'est là que l'anti-GOTO le mouvement est venu de.

Aller À une sorte de stand-in pour les "vrais" la gestion des exceptions dans certains cas.Considérer:

ptr = malloc(size);
if (!ptr) goto label_fail;
bytes_in = read(f_in,ptr,size);
if (bytes_in=<0) goto label_fail;
bytes_out = write(f_out,ptr,bytes_in);
if (bytes_out != bytes_in) goto label_fail;

Évidemment, ce code a été simplifié pour prendre moins de place, donc ne soyez pas trop accroché sur les détails.Mais envisager un autre que j'ai vu de trop nombreuses fois dans la production code par des codeurs va absurde longueurs d'éviter d'utiliser des goto:

success=false;
do {
    ptr = malloc(size);
    if (!ptr) break;
    bytes_in = read(f_in,ptr,size);
    if (count=<0) break;
    bytes_out = write(f_out,ptr,bytes_in);
    if (bytes_out != bytes_in) break;
    success = true;
} while (false);

Maintenant fonctionnellement ce code fait exactement la même chose.En fait, le code généré par le compilateur est presque identique.Toutefois, dans le programmateur du zèle pour apaiser Nogoto (le redoutable dieu de universitaire réprimande), ce programmeur a complètement brisé le sous-jacent de l'idiome que l' while boucle représente, et a un nombre réel sur la lisibilité du code. Ce n'est pas mieux.

Donc, la morale de l'histoire est, si vous vous trouvez avoir recours à quelque chose de vraiment stupide pour éviter l'utilisation de goto, alors ne le faites pas.

Donald E.Knuth a répondu à cette question dans le livre "Literate Programming", 1992 CSLI.Sur p.17 il y a un essai "La Programmation structurée avec les Instructions goto"(PDF).Je pense que l'article pourrait avoir été publiés dans d'autres livres aussi.

L'article décrit Dijkstra, de la suggestion et décrit les cas où cela est valide.Mais il donne aussi un certain nombre de contre-exemples (problèmes et algorithmes) qui ne peuvent être facilement reproduits en utilisant des boucles seulement.

L'article contient une description complète du problème, de l'histoire, des exemples et des contre exemples.

Attirés par Jay Ballou l'ajout d'une réponse, je vais ajouter mes £0.02.Si Bruno Ranschaert n'est pas déjà fait, je l'ai mentionné Knuth "de la Programmation Structurée avec les Instructions GOTO" de l'article.

Une chose que je n'ai pas vu discuté est le genre de code qui, bien que pas exactement commune, a enseigné à l'Fortran des livres de texte.Des choses comme la gamme étendue d'une boucle et d'ouvrir codée sous-routines (rappelez-vous, ce serait Fortran II, ou Fortran IV, ou Fortran 66 - pas le Fortran 77 et 90).Il y a au moins une chance que le syntaxiques détails sont inexacts, mais les concepts doivent être suffisamment précis.Les extraits de code dans chaque cas, sont à l'intérieur d'une seule fonction.

Notez que le excellente, mais la date et de l'impression) livre"Les Éléments de Style de Programmation, 2ème Édition"par Kernighan & Plauger comprend quelques exemples de la vie réelle de l'abus de GOTO de programmation texte des livres de son époque (fin des années' 70).Le matériel ci-dessous n'est pas de ce livre, cependant.

Gamme étendue pour une boucle DO

       do 10 i = 1,30
           ...blah...
           ...blah...
           if (k.gt.4) goto 37
91         ...blah...
           ...blah...
10     continue
       ...blah...
       return
37     ...some computation...
       goto 91

L'une des raisons pour de telles absurdités était le bon vieux coup de poing de la carte.Vous remarquerez peut-être que les étiquettes (gentiment hors de la séquence parce que c'était canonique!) sont dans la colonne 1 (en fait, ils devaient être dans les colonnes 1 à 5) et le code est dans les colonnes 7-72 (colonne 6 était la continuation de marqueur de colonne).Les colonnes 73-80 serait donné un numéro de séquence, et il y avait des machines qui allaient sorte de poinçon de carte de ponts dans le numéro de séquence de la commande.Si vous avez eu votre programme sur la séquence de cartes et nécessaire pour ajouter un peu de cartes (lignes) dans le milieu d'une boucle, vous auriez à repunch tout, après ces lignes supplémentaires.Toutefois, si vous avez remplacé une carte avec le GOTO choses, vous pourriez éviter de remise en ordre toutes les cartes - vous juste caché les nouvelles cartes à la fin de la routine avec de nouveaux numéros de séquence.Considérons la première tentative de "green computing" - une économie de cartes perforées (ou, plus précisément, une économie de retaper du travail et une économie d'consécutifs à ressaisir des erreurs).

Oh, vous risquez également de noter que je suis de tricher et de ne pas crier - Fortran IV a été écrit dans tous les cas supérieur normalement.

Ouvrir codé de la sous-routine

       ...blah...
       i = 1
       goto 76
123    ...blah...
       ...blah...
       i = 2
       goto 76
79     ...blah...
       ...blah...
       goto 54
       ...blah...
12     continue
       return
76     ...calculate something...
       ...blah...
       goto (123, 79) i
54     ...more calculation...
       goto 12

Le GOTO entre les étiquettes de 76 et 54 est une version de la goto.Si la variable i a la valeur 1, goto la première étiquette de la liste (123);si elle a la valeur 2, passez à la deuxième, et ainsi de suite.Le fragment de 76 à l'aide de goto est l'ouverture codée sous-routine.C'est un morceau de code d'exécution plutôt comme une sous-routine, mais écrite dans le corps d'une fonction.(Fortran avait également l'énoncé des fonctions qui ont été intégrés fonctions intégrée sur une seule ligne).

Il y avait pire des constructions que le calcul des goto - vous pouvez assigner des étiquettes de variables et d'utiliser ensuite une assigné goto.Googler attribué goto me dit qu'il a été supprimé à partir Fortran 95.Une victoire pour la programmation structurée révolution qui pourrait raisonnablement être dit avoir commencé en public avec Dijkstra du "GOTO Considéré comme Nocif" lettre ou un article.

Sans en connaître les sortes de choses qui ont été faites dans le Fortran (et dans d'autres langues, dont la plupart ont, à juste titre, tombé dans l'oubli), il est difficile pour nous les nouveaux arrivants à comprendre la portée du problème qui Dijkstra a été de traiter avec.Zut, je n'ai pas commencer la programmation jusqu'à dix ans après cette lettre a été publiée (mais j'ai eu le malheur de programme en Fortran IV pour un temps).

Goto jugé utile.

J'ai commencé la programmation en 1975.De datant des années 1970 programmeurs, les mots "goto considéré comme nocif", a dit plus ou moins que de nouveaux langages de programmation modernes, les structures de contrôle ont été la peine d'essayer.Nous avons essayé les nouvelles langues.Rapidement, nous nous sommes convertis.Nous ne revint jamais.

Nous ne sommes jamais allés en arrière, mais, si vous êtes plus jeune, vous n'avez jamais été là en premier lieu.

Maintenant, un arrière-plan dans les anciens langages de programmation peut-être pas très utile, sauf comme un indicateur de l'entreprise de programmation de l'âge.Nonobstant, les jeunes programmeurs n'ont pas cette formation, de sorte qu'ils ne comprennent plus le message le slogan "goto considéré comme nocif" transmis à son public cible au moment où il a été introduit.

Les Slogans on ne comprend pas ne sont pas très éclairante.Il est probablement préférable d'oublier de tels slogans.Ces slogans ne pas aider.

Ce slogan cependant, "Goto considéré comme nocif," a pris un mort-vivant de sa propre vie.

Peut goto ne pas être maltraités?Réponse:bien sûr, mais alors quoi?Pratiquement chaque élément de programmation peut être abusé.L'humble bool par exemple, est maltraité plus souvent que certains d'entre nous aimeraient croire.

En revanche, je ne me souviens pas de réunion d'un seul, l'instance réelle de goto abus depuis 1990.

Le plus gros problème avec le goto n'est probablement pas technique, mais sociale.Les programmeurs qui n'en savons pas beaucoup semblent parfois l'impression que la dépréciation goto rend son smart.Vous pourriez avoir à répondre à ces programmeurs de temps à autre.Telle est la vie.

La pire chose à propos de goto aujourd'hui, c'est qu'il n'est pas suffisamment utilisé.

Il n'y a pas de choses telles que GOTO considéré comme nocif.

GOTO est un outil, et comme tous les outils, il peut être utilisé et abusé.

Il ya, cependant, de nombreux outils dans le monde de la programmation qui ont tendance à être abusé en plus d'être utilisé, et GOTO est l'un d'entre eux.l' AVEC déclaration de Delphes est une autre.

Personnellement, je n'utilisons pas dans typique du code, mais j'ai eu l'étrange usage des deux GOTO et AVEC qui a lieu, et une solution alternative aurait contenu plus de code.

La meilleure solution serait que le compilateur juste vous avertir que le mot d'ordre était teintées, et vous auriez à farcir une couple de directives pragma autour de l'état de se débarrasser des mises en garde.

C'est comme dire à vos enfants de ne pas courir avec des ciseaux.Les ciseaux ne sont pas mauvais, mais l'utilisation de certains d'entre eux sont peut-être pas la meilleure façon de garder votre santé.

Depuis que j'ai commencé à faire quelques choses dans le noyau linux, gotos ne me dérange pas tellement comme ils le faisaient.Au début j'étais horrifié de voir, ils (les gars du noyau) ajouté gotos dans mon code.Depuis, j'ai pris l'habitude de l'utilisation des gotos, dans certains contextes, et va maintenant utiliser parfois moi-même.Typiquement, c'est un goto qui saute à la fin d'une fonction pour faire une sorte de nettoyage et de renflouer, plutôt que de dupliquer le même nettoyage et de sauvetage en plusieurs endroits dans la fonction.Et généralement, ce n'est pas quelque chose d'assez grand pour s'en remettre à une autre fonction (par exemple,libérer localement (k)malloc ed variables est un cas typique.

J'ai écrit le code utilisé setjmp/longjmp qu'une seule fois.Il était dans une batterie MIDI séquenceur programme.La lecture qui s'est passé dans un processus distinct de toutes les interactions avec l'utilisateur, et le processus de lecture utilisé de la mémoire partagée avec l'INTERFACE utilisateur du processus pour obtenir le peu d'info qu'elle devait faire la lecture.Lorsque l'utilisateur a voulu arrêter la lecture, le processus de lecture juste fait un longjmp "retour au début" pour recommencer, plutôt que certains compliqué le déroulement de là où il est arrivé à être en cours d'exécution lorsque l'utilisateur a voulu arrêter.Il a travaillé beaucoup, était simple, et je n'ai jamais eu de problèmes ou de bugs liés à elle dans cette instance.

setjmp/longjmp ont leur place, mais ce lieu est l'un vous ne serez pas probablement visiter, mais une fois dans un très long moment.

Edit:J'ai juste regardé le code.C'était en fait siglongjmp() que j'ai utilisé, pas longjmp (non pas que c'est une grosse affaire, mais j'avais oublié que siglongjmp même existé.)

Il n'a jamais été, aussi longtemps que vous êtes capable de penser par vous-même.

Si vous êtes à la rédaction d'une VM en C, il s'avère que l'utilisation de gcc (s) calculé gotos comme ceci:

char run(char *pc) {
    void *opcodes[3] = {&&op_inc, &&op_lda_direct, &&op_hlt};
    #define NEXT_INSTR(stride) goto *(opcodes[*(pc += stride)])
    NEXT_INSTR(0);
    op_inc:
    ++acc;
    NEXT_INSTR(1);
    op_lda_direct:
    acc = ram[++pc];
    NEXT_INSTR(1);
    op_hlt:
    return acc;
}

fonctionne beaucoup plus vite que l'interrupteur conventionnel à l'intérieur d'une boucle.

Parce que goto peut être utilisé pour la confusion métaprogrammation

Goto est à la fois un de haut niveau et un de bas niveau contrôle de l'expression, et comme un résultat, il n'a tout simplement pas avoir une conception appropriée modèle approprié pour la plupart des problèmes.

C'est de bas niveau dans le sens qu'un goto est une primitive de l'opération qui met en œuvre quelque chose de plus élevé, comme while ou foreach ou quelque chose.

C'est de haut niveau dans le sens que lorsqu'il est utilisé d'une certaine façon, il prend le code qui s'exécute dans un enchaînement clair, d'une manière ininterrompue, sauf pour structurer les boucles et les changements dans les pièces de la logique, qui sont, avec assez de gotos, un sac de logique étant dynamiquement remonté.

Donc, il y a un prosaïque et un le mal côté d' goto.

L' prosaïque côté c'est que la hausse de pointage goto peut mettre en œuvre est parfaitement raisonnable boucle et une pointe vers le bas goto peut faire tout à fait raisonnable break ou return.Bien sûr, une réelle while, break, ou return serait beaucoup plus lisible, que le pauvre homme n'aurait pas à simuler l'effet de la goto afin d'obtenir la grande image.Ainsi, une mauvaise idée en général.

L' mauvais côté implique une routine pour ne pas utiliser goto pour tout, casser, ou de retour, mais en l'utilisant, pour ce qu'on appelle spaghetti logique.Dans ce cas, le goto-développeur heureux est la construction des morceaux de code d'un labyrinthe de goto, et la seule façon de le comprendre est de simuler mentalement comme un ensemble, un très fatigant de la tâche quand il y a beaucoup de goto.Je veux dire, imaginez la difficulté de l'évaluation de code où l' else n'est pas précisément de l'inverse de la if, où imbriquée ifs pourrait permettre à certaines choses qui ont été rejetées par l'extérieur if, etc, etc.

Enfin, pour vraiment couvrir le sujet, il convient de noter que l'essentiel de toutes les langues sauf l'Algol d'abord fait une seule déclarations sous réserve de leurs versions de if-then-else.Donc, la seule façon de faire un bloc conditionnel a été à goto autour d'elle à l'aide d'un inverse conditionnelle.Fou, je sais, mais j'ai lu quelques anciennes spécifications.Rappelez-vous que les premiers ordinateurs ont été programmés en binaire en code machine donc je suppose que tout genre d'un HLL a été une bouée de sauvetage;Je suppose qu'ils ne sont pas trop pointilleux sur exactement ce que HLL caractéristiques qu'ils ont obtenu.

Ayant dit tout ce que j'ai utilisé pour coller une goto dans chaque programme que j'ai écrit "juste pour embêter les puristes".

Refusant l'utilisation de l'instruction GOTO pour les programmeurs, c'est comme dire d'un charpentier de ne pas utiliser un marteau, comme cela risque d'endommager le mur pendant qu'il bat à un clou.Un vrai programmeur Sait Comment et Quand utiliser un GOTO.J'ai suivi derrière certaines de ces soi-disant "Programmes Structurés de" je viens voir ces Horribles code juste pour éviter d'utiliser un GOTO, que j'ai pu tirer le programmeur.Ok, pour la défense de l'autre côté, j'ai vu certains réel de code spaghetti trop et encore une fois, les programmeurs doivent être abattus trop.

Voici juste un petit exemple de code que j'ai trouvé.

  YORN = ''
  LOOP
  UNTIL YORN = 'Y' OR YORN = 'N' DO
     CRT 'Is this correct? (Y/N) : ':
     INPUT YORN
  REPEAT
  IF YORN = 'N' THEN
     CRT 'Aborted!'
     STOP
  END

-----------------------OU----------------------

10:  CRT 'Is this Correct (Y)es/(N)o ':

     INPUT YORN

     IF YORN='N' THEN
        CRT 'Aborted!'
        STOP
     ENDIF
     IF YORN<>'Y' THEN GOTO 10

"Dans ce lien http://kerneltrap.org/node/553/2131"

Ironiquement, en éliminant le goto a introduit un bug:le spinlock appel a été omis.

Le document original doit être considéré comme "Inconditionnel GOTO Considéré comme Nocif".Il a été notamment en prônant une forme de programmation conditionnelle (if) et itératif (while) les constructions, plutôt que de le tester et de saut commun au début du code. goto est toujours utile dans certaines langues ou à des circonstances où il n'y a pas de contrôle de la structure existe.

À propos de l'endroit je suis d'accord Goto pourrait être utilisé, c'est quand vous avez besoin de traiter avec des erreurs, et chaque point particulier, une erreur se produit nécessite un traitement spécial.

Par exemple, si vous êtes à l'accaparement des ressources et à l'aide de sémaphores ou mutex, vous avez à les attraper dans l'ordre et vous devriez toujours les diffuser de façon opposée.

Certains de code nécessite un très étrange motif de s'emparer de ces ressources, et vous ne pouvez pas écrire un facilement comprendre et à maintenir une structure de contrôle pour gérer correctement à la fois le saisissant et en le libérant de ces ressources afin d'éviter un blocage.

Il est toujours possible de le faire sans goto, mais dans ce cas, et quelques autres Goto est en fait la meilleure solution principalement pour des raisons de lisibilité et de facilité de maintenance.

-Adam

Un moderne GOTO usage est par le compilateur C# pour créer des machines d'état pour les agents recenseurs défini par le taux de retour.

GOTO est quelque chose qui devrait être utilisé par les compilateurs et les non-programmeurs.

Jusqu'à ce que le C et le C++ (parmi d'autres coupables) ont marqué les pauses et continue, goto continuera à avoir un rôle.

Si GOTO lui-même étaient mauvaises, les compilateurs serait mal, parce qu'ils génèrent des JMPs.Si sauter dans un bloc de code, en particulier à la suite d'un pointeur, ont été de mauvais en soi, l'instruction de Retour serait le mal.Plutôt, le mal est dans le potentiel d'abus.

Parfois, j'ai eu à écrire des applications qui ont dû suivre un certain nombre d'objets, où chaque objet a dû suivre un complexe séquence d'états en réponse à des événements, mais la chose était certainement le seul thread.Une séquence typique des états, si elle est représentée en pseudo-code:

request something
wait for it to be done
while some condition
    request something
    wait for it
    if one response
        while another condition
            request something
            wait for it
            do something
        endwhile
        request one more thing
        wait for it
    else if some other response
        ... some other similar sequence ...
    ... etc, etc.
endwhile

Je suis sûr que ce n'est pas nouveau, mais la façon dont j'ai géré ça en C(++) était de définir des macros:

#define WAIT(n) do{state=(n); enque(this); return; L##n:;}while(0)
#define DONE state = -1

#define DISPATCH0 if state < 0) return;
#define DISPATCH1 if(state==1) goto L1; DISPATCH0
#define DISPATCH2 if(state==2) goto L2; DISPATCH1
#define DISPATCH3 if(state==3) goto L3; DISPATCH2
#define DISPATCH4 if(state==4) goto L4; DISPATCH3
... as needed ...

Alors (en supposant que l'état est initialement 0) de la structuration de la machine d'état ci-dessus se transforme en code structuré:

{
    DISPATCH4; // or as high a number as needed
    request something;
    WAIT(1); // each WAIT has a different number
    while (some condition){
        request something;
        WAIT(2);
        if (one response){
            while (another condition){
                request something;
                WAIT(3);
                do something;
            }
            request one more thing;
            WAIT(4);
        }
        else if (some other response){
            ... some other similar sequence ...
        }
        ... etc, etc.
    }
    DONE;
}

Une variation sur ce, il peut y avoir d'APPEL et de RETOUR, de sorte que certaines machines peuvent agir comme des sous-routines d'autres machines d'état.

Est-il inhabituel?Oui.Faut-il un certain apprentissage de la part de la responsable?Oui.N'est que l'apprentissage de payer?Je pense que oui.Pourrait-il être fait sans GOTOs que sauter dans les blocs?Nope.

J'évite depuis un collaborateur/manager sera sans doute question de son utilisation dans une revue de code, ou quand ils trébuchent à travers elle.Alors que je pense qu'il a utilise (la gestion d'erreur par exemple) - tu vas courir à l'encontre de certains autres développeurs qui ont un certain type de problème avec elle.

C'est pas la peine.

En fait je me suis trouvé obligé d'utiliser un goto, parce que je n'arrivais pas à penser à une meilleure (plus rapide) pour écrire ce code:

J'ai eu un objet complexe, et j'avais besoin de faire une opération sur elle.Si l'objet est dans un état, alors je pourrais faire une version rapide de l'opération, sinon j'ai eu à faire une version lente de l'opération.La chose est que, dans certains cas, dans le milieu de la lenteur de l'opération, il a été possible de réaliser que cela pourrait avoir été fait avec la rapidité de l'opération.

SomeObject someObject;    

if (someObject.IsComplex())    // this test is trivial
{
    // begin slow calculations here
    if (result of calculations)
    {
        // just discovered that I could use the fast calculation !
        goto Fast_Calculations;
    }
    // do the rest of the slow calculations here
    return;
}

if (someObject.IsmediumComplex())    // this test is slightly less trivial
{
    Fast_Calculations:
    // Do fast calculations
    return;
}

// object is simple, no calculations needed.

C'était dans une vitesse critique en temps réel sur le code de l'INTERFACE utilisateur, donc je pense honnêtement qu'un GOTO a été justifié ici.

Hugo

Presque toutes les situations où un goto peut être utilisé, vous pouvez faire de même en utilisant d'autres constructions.Goto est utilisé par le compilateur de toute façon.

Personnellement, je ne l'utilise jamais explicitement, ne pas avoir besoin de.

Une chose que je n'ai pas vu de tout des réponses ici est qu'un "goto" solution est souvent plus efficace que l'un de la programmation structurée des solutions souvent mentionné.

Considérer les nombreuses imbrications de boucles cas, où à l'aide de 'goto' au lieu d'un tas de if(breakVariable) sections est évidemment plus efficace.La solution de "Mettre vos boucles dans une fonction et l'utilisation du retour" est souvent totalement déraisonnable.Dans le cas probable que les boucles sont à l'aide de variables locales, vous avez maintenant à tous les passer à travers les paramètres de la fonction, potentiellement manipuler des charges supplémentaires des maux de tête qui surviennent à partir de cela.

Considérons maintenant le nettoyage des cas, que j'ai moi-même utilisé assez souvent, et c'est tellement commun que d'avoir sans doute été responsable pour le try{} catch {} structure non disponible dans de nombreuses langues.Le nombre de contrôles et de variables supplémentaires qui sont nécessaires pour accomplir la même chose, ils sont bien pire que l'un ou deux des instructions pour effectuer le saut, et de nouveau, la fonction supplémentaire de la solution n'est pas une solution du tout.Vous ne pouvez pas me dire que c'est plus facile à gérer ou des plus lisible.

Maintenant, le code de l'espace, de l'utilisation des piles, et le temps d'exécution peut être suffisant dans de nombreuses situations de beaucoup de programmeurs, mais quand vous êtes dans un environnement embarqué avec seulement 2 ko de code de l'espace de travail avec, 50 octets des instructions supplémentaires pour éviter un clairement défini "goto" est juste risible, et ce n'est pas aussi rare qu'une situation de haut niveau programmeurs croire.

La déclaration que "goto est nuisible' a été très utile dans la voie de la programmation structurée, même si elle était toujours une sur-généralisation.À ce stade, nous avons tous entendu parler, il suffit de se méfier de l'utiliser (comme nous).Quand il est de toute évidence le bon outil pour le travail, nous n'avons pas besoin d'avoir peur d'elle.

Vous pouvez l'utiliser pour briser à partir d'un profond boucle imbriquée, mais la plupart du temps, votre code peut être remaniée pour être plus propre, sans profondément boucles imbriquées.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top