Pour tous ceux qui tombent sur ce fil de discussion et qui lisent toutes les déclarations du genre "goto ne sert à rien". Je peux rapidement citer un exemple extrêmement utile :
Sans goto 1 :
int count = 1000;
char* mystring = malloc(sizeof(char)*count);
bool foundPair = false;
for(int i = 0; i < count - 1;i++)
{
for(int j = i+1; j < count; j++)
{
if(*char[i] == *char[j]) foundPair = true;
if(foundPair) break;
}
if(foundPair) break;
}
Sans goto 2 :
int count = 1000;
char* mystring = malloc(sizeof(char)*count);
bool foundPair = false;
for(int i = 0; i < count - 1 && !foundPair;i++)
{
for(int j = i+1; j < count && !foundPair; j++)
{
if(*char[i] == *char[j]) foundPair = true;
}
}
i--; j--;
Avec goto :
int count = 1000;
char* mystring = malloc(sizeof(char)*count);
for(int i = 0; i < count - 1;i++)
{
for(int j = i+1; j < count; j++)
{
if(*char[i] == *char[j]) goto foundPair;
}
}
goto nopair:
foundPair: .....
noPair: ..whatever
Cela supprime 1) la nécessité de créer un booléen en mémoire, 2) une instruction d'affectation et 3) deux instructions de comparaison. Beaucoup de conneries juste pour sortir des boucles internes où un simple saut au niveau de l'assemblage (i.e. goto) est beaucoup plus efficace.
Nous savons tous aussi que, le plus souvent, un programme VA se retrouver avec des boucles for imbriquées pour les recherches, les opérations complexes (comme l'algorithme scrypt), etc. Chacun de ces octets pour une vérification booléenne s'additionne. Chacun de ces octets pour un contrôle booléen s'additionne. Une affectation supplémentaire de la mémoire à un registre peut interférer avec le cache et le pipeline comme un fou et, même si ce n'est pas le cas, l'affectation est toujours lente. Ensuite, les comparaisons supplémentaires ne font qu'ajouter des problèmes de cache et de pipeline. Ajoutez à cela le fait que de nombreux langages de haut niveau comme Java et .Net (C#, F#, etc.) exécutent un code d'octet dans un environnement d'exécution interprété et vous obtenez une surcharge encore plus importante pour chacune de ces opérations qu'au simple niveau de la machine.
La seule autre "alternative" est de placer la boucle for imbriquée dans une fonction à part entière et de renvoyer une valeur :
bool HasPair(char* mystring, int strlen)
{
for(int i = 0; i < count - 1;i++)
{
for(int j = i + 1; j < count; j++)
{
if(*char[i] == *char[j]) return true;
}
}
return false;
}
int count = 1000;
char* mystring = malloc(sizeof(char)*count);
if(HasPair(mystring,1000))
{
//do something
}
Cependant, cela ajoute la surcharge d'un appel de fonction : mise à jour du pointeur de pile, insertion des deux variables et d'autres informations sur la pile, retrait de tout cela de la pile, et enfin retrait de la variable de la pile. Sans compter que si la valeur de retour était plus complexe (notre exemple est relativement simple), nous devrions retourner, par exemple, i et j, si les adresses et non les valeurs sont importantes.
Étant donné que la plupart des langages ne permettent pas de renvoyer plusieurs variables nommées (c'est-à-dire que les variables multiples nécessitent un tableau, une structure ou un objet quelconque), il faut créer un nouveau type de retour, allouer de la mémoire pour ce type, attribuer les valeurs i et j (ou toute autre valeur à attribuer) et enfin renvoyer le pointeur/l'instance du type.
En résumé, les goto sont extrêmement utiles si vous voulez sauter plusieurs opérations inutiles et, en général, c'est le seul moyen de sortir efficacement des boucles imbriquées de type for, while et do sans ajouter une complexité excessive à votre application.
Faire tourner de simples applications de bureau, qui s'en soucie vraiment de nos jours, n'est-ce pas ? Mais, si vous parlez de choses comme les fonctions centrales des noyaux Linux, iOS, Windows, etc., alors l'accélération de ces types de fonctions est extrêmement importante. Ou, pour les personnes qui programment des applications pour les téléphones intelligents, il est important de tirer le maximum de vitesse des petits processeurs et des piles. Il en va de même pour la programmation de jeux. La plupart des opérations mathématiques sur les matrices, etc. finissent par nécessiter de multiples boucles et nous savons tous que nous voulons que chaque bit de puissance de traitement soit utilisé à bon escient afin d'avoir une expérience réaliste dans nos jeux.
-RJS
5 votes
Non, il n'y a pas
goto
dans bash (au moins il est ditcommand not found
pour moi). Pourquoi ? Il y a de fortes chances qu'il y ait un meilleur moyen de le faire.4 votes
Vous n'avez jamais besoin de goto, au pire vous avez besoin de plus de pratique avec d'autres outils de flux de contrôle.
171 votes
Il a peut-être ses raisons. J'ai trouvé cette question parce que je veux un
goto
pour passer au-dessus d'une grande quantité de code afin de déboguer un grand script sans attendre une heure pour que diverses tâches non liées se terminent. Je n'utiliserais certainement pas ungoto
dans le code de production, mais pour le débogage de mon code, cela me faciliterait infiniment la vie, et il serait plus facile de le repérer quand il faudrait le supprimer.33 votes
@delnan Mais ne pas avoir de goto peut rendre certaines choses plus compliquées. Il existe en effet des cas d'utilisation.
0 votes
Il serait utile que vous précisiez la raison pour laquelle vous en avez besoin. Si c'est pour la gestion des exceptions, créez une fonction avec une déclaration de sortie et appelez cette fonction... Aussi, si vous avez un grand script avec beaucoup d'instructions de débogage, if serait beaucoup plus lisible avec une instruction if ou le diviser en plusieurs fonctions. Ce n'est pas une bonne idée de créer des script de Bash de plusieurs centaines de lignes sans les diviser en plusieurs fonctions, comme dans tout autre langage de programmation.
1 votes
@KarlNicoll Je le veux aussi pour le débogage. Nous ne nous soucierons pas des meilleures pratiques lors du débogage du code.
82 votes
J'en ai marre de ce mythe du goto ! Il n'y a rien de mal avec goto ! Tout ce que vous écrivez devient éventuellement goto. En assembleur, il n'y a que goto. Une bonne raison d'utiliser le goto dans les langages de programmation supérieurs est par exemple de sortir de boucles imbriquées de manière propre et lisible.
2 votes
@alexc Désolé, mais non - sauter hors des boucles imbriquées est exactement (une des) raisons pour lesquelles tant de gens détestent goto ! Il y a des cas d'utilisation raisonnables, mais ce n'est pas l'un d'entre eux, et même si c'était le cas, ce ne serait qu'une raison pour avoir des instructions continues à plusieurs niveaux ; pas un goto généralisé. Néanmoins, vous avez raison - et je suis d'accord avec votre conclusion, même si ce n'est pas votre exemple.
2 votes
J'ai la pire des raisons - porter les fichiers cmd de Windows plus ou moins 1:1 vers bash. Ils sont généralement peu ou pas structurés, sauf au niveau "goto"...
30 votes
"Éviter d'avoir" est une excellente règle. Comme toute règle, elle doit être apprise en trois phases. Premièrement : suivre la règle jusqu'à ce qu'elle devienne une seconde nature. Deuxièmement, apprenez à comprendre les raisons de la règle. Troisièmement, apprenez les bonnes exceptions à la règle, sur la base d'une compréhension globale de la manière de suivre la règle et de ses raisons. Évitez de sauter les étapes ci-dessus, ce qui reviendrait à utiliser "goto" ;-)
1 votes
Le shell avait l'habitude d'avoir un
goto
commande. Le site:
qui permet de créer une étiquette en est un rudiment. Cependant, cette fonctionnalité n'existe plus aujourd'hui.1 votes
Je pense que nous avons découvert le problème. GOTO a été omis du shell. Qui peut nous aider à réparer cet oubli ?
0 votes
Le shell C a un goto : linux.die.net/man/1/csh
0 votes
Goto est "considéré comme nuisible" mais si vous l'utilisez, n'en avez pas plusieurs qui croisent les lignes d'autres commandes gogo. Par exemple, n'ayez pas un gogo qui saute de la ligne 1 à la ligne 5 puis un autre qui saute à la ligne 3. Cela provoque des spaghettis cauchemardesques. De même, le fait de ne sauter que vers l'avant est une autre bonne ligne de conduite.
0 votes
@StefanHegny C'est sans doute à cause de l'empressement avec lequel
%expansion%
se trouve dans le langage DOS/Windows command.com/cmd.exe ; vous trouverez tout ce qu'il faut savoir à ce sujet danshelp set
.