Tout structure de contrôle est un GOTO caché que ce soit le if, le while ou le for par exemple.
Je ne suis pas d'accord pour dire ça comme ça. Au niveau assembleur, un goto est bien entendu un branchement inconditionnel, et peut viser une adresse arbitraire (jmp <ADRESSE_ARBITRAIRE>). La seule sémantique de goto est de se brancher là où on lui dit. La sémantique du if est celle d'un branchement conditionnel, qui va à une adresse relative (jne <DÉPLACEMENT_RELATIF>). Les structures de boucle while et for font appel à un branchement conditionnel et un branchement inconditionnel. On part de :
while(condition){corps;}apres_la_boucle;
On arrive à quelque chose de ce genre (avec une « traduction » asm naïve) :
BOUCLE:if(!condition)gotoAPRES_LA_BOUCLE;// par exemple: jge APRES_LA_BOUCLEcorps;gotoBOUCLE;// jmp BOUCLEAPRES_LA_BOUCLE:apres_la_boucle;
Mais il y a une sémantique très spécifique qui limite où le saut peut s'effectuer (si tu veux, on pourrait dire qu'un if ou une boucle ont certes une étiquette implicite, mais on sait exactement où elle est placée). Avec des branchements inconditionnels « relatifs », de type break ou continue, c'est la même chose: dans le cas du break on effectuera un jmp APRÈS_LA_BOUCLE et dans le cas d'un continue ce sera jmp BOUCLE, mais tout est confiné correctement. Dans tous les cas, tu as la garantie que tu ne peux pas atterrir dans une portion de code arbitrairement, comme par exemple:
inta=0;voidfoo(intn){if(n==0)gotoLABEL;// wah trop bien hé, t'as vu l'optim' ?// reste du code...}// plein de fonctions entre les deuxintbar(void){LABEL:++a;}
Les exceptions sont quelque chose d'intermédiaire entre le goto et les branchements conditionnels selon moi: elles ressemblent à une forme de « gotos typés ». Exactement comme avec un goto, il faut spécifier des labels à des endroits précis (grâce à la construction try { ... } catch(...)). Contrairement à un goto, il y a un minimum de maîtrise sur où le saut peut arriver (car try/catch est bien une structure de contrôle), mais les sauts peuvent être bien plus longs que la portée lexicale d'un bloc (comme c'est le cas pour if/while/for/break/continue).
Ce qui pose problème ce n'est pas les exceptions, c'est la gestion des exceptions par le C++. En Java le fait d'obliger à déclarer les exceptions qu'une méthode lève (mis à par les RuntimeException) réduit de beaucoup le problème de lecture du flow d’exécution
Ça par contre je suis tout à fait d'accord : forcer à déclarer quelles exceptions peuvent être levées permet au compilateur d'engueuler le programmeur qui spécifie des « étiquettes » n'importe comment, et de préciser s'il veut traiter une exception ou non.
Ça n'empêche pas qu'il est parfaitement possible d'utiliser les exceptions non pas comme un mécanisme de gestion d'erreurs, mais comme un mécanisme de « goto contrôlé ».
[^] # Re: En vrac
Posté par lasher . En réponse au journal Pourquoi empaqueter KDE prend-il du temps ?. Évalué à 4. Dernière modification le 21 août 2014 à 19:14.
Je ne suis pas d'accord pour dire ça comme ça. Au niveau assembleur, un
gotoest bien entendu un branchement inconditionnel, et peut viser une adresse arbitraire (jmp <ADRESSE_ARBITRAIRE>). La seule sémantique degotoest de se brancher là où on lui dit. La sémantique duifest celle d'un branchement conditionnel, qui va à une adresse relative (jne <DÉPLACEMENT_RELATIF>). Les structures de bouclewhileetforfont appel à un branchement conditionnel et un branchement inconditionnel. On part de :On arrive à quelque chose de ce genre (avec une « traduction » asm naïve) :
Mais il y a une sémantique très spécifique qui limite où le saut peut s'effectuer (si tu veux, on pourrait dire qu'un
ifou une boucle ont certes une étiquette implicite, mais on sait exactement où elle est placée). Avec des branchements inconditionnels « relatifs », de typebreakoucontinue, c'est la même chose: dans le cas du break on effectuera unjmp APRÈS_LA_BOUCLEet dans le cas d'uncontinuece serajmp BOUCLE, mais tout est confiné correctement. Dans tous les cas, tu as la garantie que tu ne peux pas atterrir dans une portion de code arbitrairement, comme par exemple:Les exceptions sont quelque chose d'intermédiaire entre le
gotoet les branchements conditionnels selon moi: elles ressemblent à une forme de «gotos typés ». Exactement comme avec ungoto, il faut spécifier des labels à des endroits précis (grâce à la constructiontry { ... } catch(...)). Contrairement à ungoto, il y a un minimum de maîtrise sur où le saut peut arriver (cartry/catchest bien une structure de contrôle), mais les sauts peuvent être bien plus longs que la portée lexicale d'un bloc (comme c'est le cas pourif/while/for/break/continue).Ça par contre je suis tout à fait d'accord : forcer à déclarer quelles exceptions peuvent être levées permet au compilateur d'engueuler le programmeur qui spécifie des « étiquettes » n'importe comment, et de préciser s'il veut traiter une exception ou non.
Ça n'empêche pas qu'il est parfaitement possible d'utiliser les exceptions non pas comme un mécanisme de gestion d'erreurs, mais comme un mécanisme de «
gotocontrôlé ».