fbpx
Wikipedia

GOTO

GOTO es una instrucción propia de los primeros lenguajes de programación, como BASIC. Esta instrucción suele existir en todos los lenguajes aunque con un mnemónico adaptado al propio lenguaje.

El propósito de la instrucción es transferir el control a un punto determinado del código, donde debe continuar la ejecución. El punto al que se salta, viene indicado por una etiqueta. GOTO es una instrucción de salto incondicional.

La instrucción GOTO ha sido menospreciada en los lenguajes de alto nivel, debido a la dificultad que presenta para poder seguir adecuadamente el flujo del programa, tan necesario para verificar y corregir los programas.

En la actualidad, la funcionalidad de la instrucción sigue existiendo en todos los lenguajes de programación, bajo nombres específicos y con un campo de uso delimitado. Por lo general se restringe su uso a una estructura específica. Lo más habitual es encontrarla como una instrucción de salida de una estructura de control (en bucles FOR...NEXT como Exit FOR, en bucles DO...LOOP como Exit DO', etc...). Y el punto al que se salta, no es arbitrario sino que se salta a puntos específicos coherentes con un flujo fácil de seguir, por lo general el salto es a la instrucción siguiente a la del final de la estructura. Es decir GOTO se ha transformado (bajo la apariencia de otra palabra reservada) como un salto incondicional, pero a un punto concreto en relación a la estructura a la que da soporte.

Variaciones

Se pueden encontrar variaciones de la instrucción GOTO. En BASIC, la instrucción ON GOTO puede seleccionar de una lista de diferentes puntos de un programa a los que saltar. Podría ser interpretado como un antecesor de la instrucción switch/case. También, en FORTRAN y algunas versiones de BASIC la línea a la que saltar podía ser indicada mediante una expresión aritmética. Esto último era evitado ya que el código se hacía aún más ilegible teniendo en cuenta la necesidad de hacer los cálculos de la expresión de control para saber el destino del flujo del programa.

Controversia sobre el uso de GOTO

A diferencia de la llamada a una función, no se requiere ningún tipo de preparación o estructura de código para utilizar un GOTO. Como resultado, es más sencillo obtener código inconsistente, incompleto o complicado de mantener. Justamente por ello en los años 60 y 70, cuando surgió la programación estructurada, la comunidad informática se expresó a favor de otras instrucciones de control (if o bucles for y do/while) en lugar de GOTO.

Tal creencia está tan arraigada que el GOTO es muy criticado por los dedicados a la enseñanza de la programación, que lo suelen desaconsejar. Por el otro lado, algunos que si bien admiten el uso de un GOTO como una práctica desaconsejable[1]​ reconocen que este es la mejor opción para algunas pocas tareas puntuales[2]​ en algunos lenguajes de programación (manejo de excepciones por ejemplo). Además, por lo general se programan macros o equivalentes para evitar la utilización de GOTO.

Una crítica famosa a la instrucción en cuestión es una carta redactada por Edsger Dijkstra llamada "Go To Statement Considered Harmful" ('Instrucción Go To Considerada Dañina'). En ella Dijkstra argumenta que el uso irrestricto de GOTO debería ser prohibido en lenguajes de alto nivel ya que dificultan el análisis y la verificación de la corrección de los programas (especialmente aquellos que contienen ciclos). Por el otro lado, Donald Knuth en su libro "Structured Programming with goto Statements" (Programación estructurada con instrucciones Goto), tiene en cuenta ciertas situaciones en las que se utilizaría GOTO. Por lo general, se trata de situaciones en las que una estructura de programación en particular no está disponible y GOTO puede simularla eficientemente.

Interacción de GOTO dentro de otras estructuras de control

La sentencia GOTO, no solo puede aparecer a lo largo del listado de instrucciones de un programa, sino que incluso puede enviar el flujo dentro de una estructura de control o fuera de la misma.

Es patente, la complejidad de entender un código cuyas estructuras de control lo estuvieran también cruzadas por sentencias GOTO. Si bien el uso de GOTO puede hacer posible situaciones de las que un lenguaje carece, el uso indiscriminado de éstas harían a un código muy difícil de entender y mantener.

Esto deriva en circunstancias especiales que se consideran a continuación:

GOTO envía del flujo fuera de una estructura de control

De modo general GOTO tiene otro enemigo, y es que cuando opera dentro de otra estructura de control que guarda punteros en la pila, si hay una sentencia GOTO que sale de la estructura de control, fuerza a que se vacíe la pila con los punteros de retorno que mantenía la estructura. Esto requiere un chequeo constante de la sentencia GOTO en busca de si aparece o no dentro de una estructura de control (Véase la sección donde se compara GOTO con otras estructuras de control, más adelante en este mismo artículo), para determinar si debe o no retirar de la pila un puntero al que aparentemente no se retornará ya. Una razón para salir de una estructura de control usando GOTO, es que dicha estructura no provea otro mecanismo de salida que llegar al final del bloque de sentencias que contiene la estructura, por lo que los diversos lenguajes han provisto una salida alternativa que solucione la operación que realiza GOTO en dichos casos y a su vez no requiere la verificación que se hacía precisa para cada GOTO, típicamente las sentencias de escape alternativas se han dado en llamar:

  • Para las estructura de control que no requieren punto de retorno. Exit flujo donde flujo es la estructura de control, tales como DO, FOR, etc...
  • Para las estructuras de control que requieren un punto de retorno, RETURN, tales como GOSUB, FUNCTION, etc..

Las sentencias EXIT, todavía están limitadas respecto de GOTO, pues EXIT siempre devuelve a la siguiente instrucción al final de la estructura de control.

Puede darse el caso en algunos lenguajes, que la ejecución de la sentencia GOTO no conlleve aparejado comprobar si salta fuera de una estructura de control y consecuentemente no elimine de la pila el puntero de retorno que se colocó al entrar a la rutina en dicho caso, a efectos del programa el control sigue dentro de dicha estructura y sigue esperando que alcance el final para volver al punto de retorno y vaciar la pila del valor de retorno, como esto ya no va a ocurrir, se está perdiendo espacio de pila con cada situación de este tipo. También podría darse el caso si algún lenguaje olvida aportar solución que al ir entregando desde la pila los sucesivos retornos, se apunte a un lugar diferente de la que el programador esperaba, por la cascada de entradas fue una y la cascada de salidas debiendo ser en orden inversa conserva una salida que nunca se va a producir, falsificando con ello todas las devoluciones anteriores a esa que se ha quedado perdida por la instrucción goto. Un modo en que algunos lenguajes solventan este problema es utilizando una pila exclusivamente local y eliminarla cuando se sale del procedimiento local, en dicho caso la dirección de retorno se guarda en una pila de ámbito mayor. Si hay punteros remanentes en la pila local no devueltos no producirán errores en cascada hacia atrás.

En situaciones así es difícil seguir la pista de saltos esperada respecto de la que el programador pretendiera hacer si no se comporta como él esperaba. También de este modo es posible hacer que el código se comporte de una forma que el lenguaje no tenía previsto en su diseño y aprovechar con ello una posible situación eficiente, para realizar determinadas tareas.

Adicionalmente para solventar los posibles problemas que el inadecuado uso de GOTO pueda originar, los lenguajes de alto nivel y que utilizan programación mediante bloques y módulos bien definidos y aislados, no permiten sobre GOTO más que operar dentro del bloque o módulo donde se aloja. Un caso típico son las modernas funciones FUNCTION, PROPERTY, etc... donde si bien un GOTO puede aparecer, no puede direccionar a un punto dentro de otra FUNCTION. No confundir este aislamiento con encapsulamiento, aunque la idea es la misma.

GOTO envía el flujo dentro de una estructura de control

Sucede de otra forma cuando un salto por GOTO nos introduce dentro de una estructura de control. Si hay instrucciones tras la etiqueta a la que se salta, éstas se ejecutan correctamente, pero al llegar a una instrucción del final, si la pila está vacía (cuando la estructura de control requiere un puntero de retorno), ocurre un error que según el lenguaje varía, y si la pila no está vacía salta a la dirección que señala el último puntero en la pila, puede considerarse un error si no era lo que perseguía el programador, toda vez que dicho puntero no fue almacenado por dicha estructura decontrol en la que se halla sino por la previa.

Esto solo sucede en aquellas estructuras de control que guardan algún puntero de retorno en la pila, por ejemplo nunca ocurrirá un error dentro de una estructura IF...THEN, ni dentro de una estructura SELECT CASE (Switch), ni DO...LOOP ya que dichas estructuras al no tener al final un punto de retorno, no necesitan almacenar en la pila dicho punto de retorno.

Normalmente, es el caso que en los lenguajes, la ejecución de la sentencia GOTO no conlleva aparejado comprobar si salta dentro de una estructura de control, ya que en principio no debe generar errores aunque tenga un puntero de retorno siempre que este puntero esté localizado en la sentencia de salida en vez de en la pila.

Se detallan, comentados 3 casos comunes:

  • Caso de estructura de control donde el puntero de retorno se almacena en la sentencia final: este suele ser DO...LOOP, loop es equivalente a un GOTO DO. En una sección del artículo más adelante, se provee una implementación de la estructura de control DO...LOOP usando GOTO, que ayudará a entender este caso. En este caso por tanto saltar dentro de una estructura DO..LOOP no proporcionará un error si se llega a la sentencia final. (ver sección anterior). El puntero de retorno de esta estructura siempre apunta al principio de la estructura, es por esto que no necesita mantenerlo en la pila t resulta suficiente con dejarlo en la sentencia final.
  • Otro caso de estructura de control que el puntero de retorno se almacena en la sentencia final, pero que si da errores: un caso de este tipo suele ser FOR...NEXT. La estructura FOR se compone de 3 secciones operativas, en la primera se inicializan los valores del bucle, en la 2ª se produce el incremento de los valores que controlan el bucle y en la 3ª sección está el bloque de sentencias que se ha de repetir. Si una sentencia GOTO lleva el flujo dentro de un bucle FOR, cuando se alcanza la sentencia NEXT esta sabe localizar el retorno hacia la 2ª sección (en este sentido se comporta como DO...LOOP, (NEXT equivale a GOTO 2ª Sección) pero al tratar de incrementar el bucle descubre que las variables que necesita el bucle no han sido inicializadas, por lo que produce un error de forma indirecta. Un bucle FOR utiliza 4 variables internamente para su propio control, una variable contador que es la que se irá incrementando, 3 variables o constantes que asigna el valor inicial, final y cantidad de incremento respectivamente.
  • Caso de estructura de control que el puntero de retorno se almacena en la pila: El caso de este tipo suele ser GOSUB. Cada vez que se ejecuta una sentencia GOSUB (FUNCTION, etc...) se guarda en la pila la dirección de origen, y cada vez que se ejecuta la sentencia RETURN, se salta a la última dirección contenida en la pila, es decir no existe un par asociado GOSUB...RETURN. Véase GOSUB para más detalles. Este caso es el más proclive a que ofrezca un comportamiento difícil de seguir.

GOTO envía el flujo desde dentro de una estructura de control a otro punto dentro

En cualquier caso puede haber innumerables sentencias GOTO dentro de una estructura de control, y recorrerla de forma arbitraria, sin que genere ningún error excepto que se alcance (ejecute su turno) una sentencia de retorno que requiera un puntero de retorno en la pila que no exista. como ya se comentó, si existen valores en la pila puede darse errores o no sobre la base de si esa es la idea que perseguía el programador o no, ya que retornará el último puntero que contenga la pila.

Comparación entre GOTO y otras instrucciones de control del flujo

GOTO es incondicional, es decir ordena el salto de ejecución del programa a una dirección concreta. El salto se solicita porque se requiere que la ejecución continúe desde allí. La problemática de esto resulta en que no resulta evidente el orden de ejecución.

Como se podrá apreciar en las sucesivas comparaciones, GOTO puede implementar todas las estructuras de control, su controversia no se deduce de su versatilidad, si no de la enajenación de claridad en que resulta su uso. Las estructuras de control de lenguajes de alto nivel están realizadas usando GOTO (típicamente JMP, y sus variantes en ensamblador).

Comparación con GOSUB

Al igual que GOTO, GOSUB tampoco acepta (en la mayoría de lenguajes que se utiliza) un salto a una dirección que no sea una constante, es decir no acepta valores desde variables sino solo desde constantes, lo que en cierto modo limita la casuística de errores en que pudiera derivar.

Una diferencia sustancial se establece con las instrucciones GOSUB (saltar a subrutina), la diferencia esencial es que gosub, tras saltar a la instrucción indicada, ejecuta un número determinado de instrucciones hasta que encuentra una instrucción RETURN, que le obliga volver a la siguiente instrucción que viene a continuación de la instrucción GOSUB. GOSUB, por tanto puede entenderse como utilizar 2 gotos, el que salta a la instrucción indicada, y el que retorna a la posición última que se guarda en la pila.

Es por esto que una instrucción GOTO, no guarda el origen de procedencia en la pila. GOSUB, debe necesariamente antes de proceder con el salto guardar en la pila la dirección desde la que salta, para que a su regreso el contador de programa incremente en una unidad.

GOSUB, por tanto delimita no solo el inicio de un grupo de instrucciones sino que también queda claro su final. GOSUB requiere una instrucción de retorno, aunque nada impide colocar varias instrucciones de forma condicionada.

En consecuencia a estas consideraciones GOSUB ofrece un paso más allá el control del flujo que GOTO por sí solo no permite, no obstante, GOTO, puede emular a GOSUB, pues, puede allí donde hubiera un RETURN, remplazarse con un GOTO a la siguiente instrucción del GOTO de origen.

Implementación de GOSUB usando GOTO

Como puede deducirse en el ejemplo a continuación, ambos hacen lo mismo, y la diferencia radica en que usando GOTO, el programador debe controlar todos los saltos (véase líneas GOTO x3), para regresar al punto de partida. GOSUB en cambio hace esto de forma automática, transparente para el programador, que se desentiende de que línea o qué dirección ha de tener el retorno, ya que este valor se guarda en la pila en el momento de procesar la sentencia GOSUB.

Nota previas para entender el ejemplo: instr representan cualquier instrucción. # representa un comentario en la línea a partir de ahí. El número que le sigue representa la continuidad en la posición de memoria, que solo sirve al efecto de comprender mejor el ejemplo. Si este número va entre paréntesis indica una posición relativa respecto de este.

ejemplo de rutina usando GOSUB...

A = 5 # x-1
instr # x
instr # x+1
GOSUB 400 # instr x+2
instr # x+3
...
...
400: # instr x+?
instr # (400)+1
instr # (400)+2
Si A es= 2 luego
instr # (400)+4
RETURN
En otro caso
instr # (400)+7
instr # (400)+8
Fin casos
RETURN

ejemplo de emulación de GOSUB usando GOTO...

instr # x
instr # x+1
GOTO 400 # instr x+2
X3: # instr x+3
...
...
400: # instr x+?
instr # (400)+1
instr # (400)+2
Si A es= 2 luego
instr # (400)+4
GOTO x3
En otro caso
instr # (400)+7
instr # (400)+8
Fin casos
GOTO x3

Comparación con IF...THEN...ELSE

Como ya se ha indicado, el salto de GOTO es incondicional, al llegar a ese punto se ejecuta y eso es todo, a un posible lector, no le queda claro cual es la razón de salto, solo sabe a ciencia cierta que la ejecución continúa en el punto indicado y nada más, para comprender mejor que sucede necesita estudiar con detenimiento las condiciones previas, lo que supone una ardua tarea, especialmente cuando se busca código optimizado para velocidad ya que entonces el mismo puede resultar más difícil de entender.

La principal diferencia entre GOTO y la sentencia IF...THEN..ELSE es que GOTO puede basar su salto en los condicionantes que se dan previamente, lo que obliga en la toma de decisiones a utilizar varias sentencias GOTO que lo hace aún más complejo de analizar.

La sentencia IF asocia el salto a un cúmulo de sucesos concretos (puede haber una o varias condiones cuya evaluación conjunta se evalúa como verdadero o falso, de modo que es posible y fácil entender que el salto se produce solo si no se cumple la condición ejecutándose, si se cumple no se salta, se continúa con las siguientes instrucciones y al final de las mismas salta hasta el final de todo el bloque que forman la sentencia y las instrucciones asociadas a sendas condiciones.

Para comprender correctamente como se produce esto es necesario distinguir la sentencia de salto condicional IF que es de alto nivel, con las instrucciones ensamblador de salto condicional (saltar si cero, saltar si no cero, etc...). Son estas últimas quienes determinan si el salto se produce dadas las condiciones.

Comparación con FOR...NEXT

Comparación con DO...LOOP (WHILE)

Comparación con FUNCION

Ejemplos

Pascal

En Pascal, donde se deben declarar las etiquetas con la palabra reservada LABEL:

Program UsoGOTO (input, output); LABEL Salto; BEGIN Writeln('Como estamos antes del GOTO esto saldrá en pantalla'); GOTO Salto; Writeln('Esto no saldrá en pantalla'); Salto: Writeln('Se efectuó una ruptura en el flujo debido a la sentencia GOTO') END. 

Pauscal

En Pauscal es posible usar la instrucción IrHacia (GoTo en español) declarando una etiqueta y estableciéndola como parámetro.

 Var i:Entero Etiqueta: i = i + 1 IrHacia Etiqueta 

C#

En Lenguaje de programación C# se declaran las etiquetas con dos puntos al final.

 static void main() { :etiqueta: //La etiqueta :goto etiqueta; //Ir a la etiqueta } 

Basic

En BASIC, las etiquetas se sentencian igual que en C, con dos puntos al final.

:PRINT "Prueba de GOTO en QBASIC" :GOTO prueba :PRINT "Esto no se ve porque hemos saltado a la etiqueta llamada prueba" :prueba: :PRINT "GOTO realizado correctamente!" 

En algunas variantes de BASIC, como por ejemplo Just BASIC o Liberty BASIC, se usa [ y ] para remarcar etiquetas:

  :PRINT "Prueba de GOTO en QBASIC" :GOTO [prueba] :PRINT "Esto no se ve porque hemos saltado a la etiqueta llamada prueba" [prueba] :PRINT "GOTO realizado correctamente!" 

Ensamblador

En ensamblador se emplean instrucciones similares. En el caso de x86 la instrucción es jmp:

# Programa para GNU/Linux. # Ensamblar con cc jmp.S -o jmp # Muestra "Comenzando bucle" y seguidamente entra en un bucle # mostrando "Hola, mundo" a cada iteración .section .rodata msg1: .string "Hola, mundo" msg2: .string "Comenzando bucle" .section .text .globl main main: movl $msg2,(%esp) call puts etiqueta: movl $msg,(%esp) call puts jmp etiqueta 

end.

Véase también

Bibliografía

  1. * Peter Bishop: Programación avanzada en BASIC, Ediciones Anaya Multimedia año-1990 ISBN 978-84-7614-013-0 (página 86):
    Una vez escrita la parte del programa correspondiente a un bucle es muy tentador aprovechar algunas o todas las instrucciones contenidas en esa parte para otros fines, lo que obliga a utilizar bifurcaciones para acceder al bucle desde otros puntos del programa (lo que se haría con GOTOs). Esa tentación debe resistirse a toda costa. Ramificar un programa hacia el interior de un bucle es una costumbre completamente desaconsejable.
  2. * Peter Bishop: Programación avanzada en BASIC, Ediciones Anaya Multimedia año-1990 ISBN 978-84-7614-013-0 (página 86):
    Otra cosa es crear una bifurcación para salir de un bucle, situación que se plantea cuando la terminación del mismo depende de más de una sola condición. Una de ellas es la llegada del contador a su valor final, y la otra supone alguna verificación realizada dentro del propio bucle. ...no es recomendable saltar directamente al exterior de un bucle. Lo mejor es pasar el contador a su valor final y saltar hasta el fin del bucle.
  •   Datos: Q750997

goto, sugerido, transferencia, incondicional, fusionado, este, artículo, sección, véase, discusión, hayas, realizado, fusión, artículos, pide, fusión, historiales, aquí, este, aviso, puesto, junio, 2014, este, artículo, sobre, informática, detectaron, varios, . Se ha sugerido que Transferencia incondicional sea fusionado en este articulo o seccion vease discusion Una vez que hayas realizado la fusion de articulos pide la fusion de historiales aqui Este aviso fue puesto el 18 de junio de 2014 En este articulo sobre informatica se detectaron varios problemas Por favor editalo para mejorarlo Necesita ser wikificado conforme a las convenciones de estilo de Wikipedia Carece de fuentes o referencias que aparezcan en una fuente acreditada Este aviso fue puesto el 12 de enero de 2013 GOTO es una instruccion propia de los primeros lenguajes de programacion como BASIC Esta instruccion suele existir en todos los lenguajes aunque con un mnemonico adaptado al propio lenguaje El proposito de la instruccion es transferir el control a un punto determinado del codigo donde debe continuar la ejecucion El punto al que se salta viene indicado por una etiqueta GOTO es una instruccion de salto incondicional La instruccion GOTO ha sido menospreciada en los lenguajes de alto nivel debido a la dificultad que presenta para poder seguir adecuadamente el flujo del programa tan necesario para verificar y corregir los programas En la actualidad la funcionalidad de la instruccion sigue existiendo en todos los lenguajes de programacion bajo nombres especificos y con un campo de uso delimitado Por lo general se restringe su uso a una estructura especifica Lo mas habitual es encontrarla como una instruccion de salida de una estructura de control en bucles FOR NEXT como Exit FOR en bucles DO LOOP como Exit DO etc Y el punto al que se salta no es arbitrario sino que se salta a puntos especificos coherentes con un flujo facil de seguir por lo general el salto es a la instruccion siguiente a la del final de la estructura Es decir GOTO se ha transformado bajo la apariencia de otra palabra reservada como un salto incondicional pero a un punto concreto en relacion a la estructura a la que da soporte Indice 1 Variaciones 2 Controversia sobre el uso de GOTO 3 Interaccion de GOTO dentro de otras estructuras de control 3 1 GOTO envia del flujo fuera de una estructura de control 3 2 GOTO envia el flujo dentro de una estructura de control 3 3 GOTO envia el flujo desde dentro de una estructura de control a otro punto dentro 4 Comparacion entre GOTO y otras instrucciones de control del flujo 4 1 Comparacion con GOSUB 4 1 1 Implementacion de GOSUB usando GOTO 4 1 2 ejemplo de rutina usando GOSUB 4 1 3 ejemplo de emulacion de GOSUB usando GOTO 4 2 Comparacion con IF THEN ELSE 4 3 Comparacion con FOR NEXT 4 4 Comparacion con DO LOOP WHILE 4 5 Comparacion con FUNCION 5 Ejemplos 5 1 Pascal 5 2 Pauscal 5 3 C 5 4 Basic 5 5 Ensamblador 6 Vease tambien 7 BibliografiaVariaciones EditarSe pueden encontrar variaciones de la instruccion GOTO En BASIC la instruccion ON GOTO puede seleccionar de una lista de diferentes puntos de un programa a los que saltar Podria ser interpretado como un antecesor de la instruccion switch case Tambien en FORTRAN y algunas versiones de BASIC la linea a la que saltar podia ser indicada mediante una expresion aritmetica Esto ultimo era evitado ya que el codigo se hacia aun mas ilegible teniendo en cuenta la necesidad de hacer los calculos de la expresion de control para saber el destino del flujo del programa Controversia sobre el uso de GOTO EditarA diferencia de la llamada a una funcion no se requiere ningun tipo de preparacion o estructura de codigo para utilizar un GOTO Como resultado es mas sencillo obtener codigo inconsistente incompleto o complicado de mantener Justamente por ello en los anos 60 y 70 cuando surgio la programacion estructurada la comunidad informatica se expreso a favor de otras instrucciones de control if o bucles for y do while en lugar de GOTO Tal creencia esta tan arraigada que el GOTO es muy criticado por los dedicados a la ensenanza de la programacion que lo suelen desaconsejar Por el otro lado algunos que si bien admiten el uso de un GOTO como una practica desaconsejable 1 reconocen que este es la mejor opcion para algunas pocas tareas puntuales 2 en algunos lenguajes de programacion manejo de excepciones por ejemplo Ademas por lo general se programan macros o equivalentes para evitar la utilizacion de GOTO Una critica famosa a la instruccion en cuestion es una carta redactada por Edsger Dijkstra llamada Go To Statement Considered Harmful Instruccion Go To Considerada Danina En ella Dijkstra argumenta que el uso irrestricto de GOTO deberia ser prohibido en lenguajes de alto nivel ya que dificultan el analisis y la verificacion de la correccion de los programas especialmente aquellos que contienen ciclos Por el otro lado Donald Knuth en su libro Structured Programming with goto Statements Programacion estructurada con instrucciones Goto tiene en cuenta ciertas situaciones en las que se utilizaria GOTO Por lo general se trata de situaciones en las que una estructura de programacion en particular no esta disponible y GOTO puede simularla eficientemente Interaccion de GOTO dentro de otras estructuras de control EditarLa sentencia GOTO no solo puede aparecer a lo largo del listado de instrucciones de un programa sino que incluso puede enviar el flujo dentro de una estructura de control o fuera de la misma Es patente la complejidad de entender un codigo cuyas estructuras de control lo estuvieran tambien cruzadas por sentencias GOTO Si bien el uso de GOTO puede hacer posible situaciones de las que un lenguaje carece el uso indiscriminado de estas harian a un codigo muy dificil de entender y mantener Esto deriva en circunstancias especiales que se consideran a continuacion GOTO envia del flujo fuera de una estructura de control Editar De modo general GOTO tiene otro enemigo y es que cuando opera dentro de otra estructura de control que guarda punteros en la pila si hay una sentencia GOTO que sale de la estructura de control fuerza a que se vacie la pila con los punteros de retorno que mantenia la estructura Esto requiere un chequeo constante de la sentencia GOTO en busca de si aparece o no dentro de una estructura de control Vease la seccion donde se compara GOTO con otras estructuras de control mas adelante en este mismo articulo para determinar si debe o no retirar de la pila un puntero al que aparentemente no se retornara ya Una razon para salir de una estructura de control usando GOTO es que dicha estructura no provea otro mecanismo de salida que llegar al final del bloque de sentencias que contiene la estructura por lo que los diversos lenguajes han provisto una salida alternativa que solucione la operacion que realiza GOTO en dichos casos y a su vez no requiere la verificacion que se hacia precisa para cada GOTO tipicamente las sentencias de escape alternativas se han dado en llamar Para las estructura de control que no requieren punto de retorno Exit flujo donde flujo es la estructura de control tales como DO FOR etc Para las estructuras de control que requieren un punto de retorno RETURN tales como GOSUB FUNCTION etc Las sentencias EXIT todavia estan limitadas respecto de GOTO pues EXIT siempre devuelve a la siguiente instruccion al final de la estructura de control Puede darse el caso en algunos lenguajes que la ejecucion de la sentencia GOTO no conlleve aparejado comprobar si salta fuera de una estructura de control y consecuentemente no elimine de la pila el puntero de retorno que se coloco al entrar a la rutina en dicho caso a efectos del programa el control sigue dentro de dicha estructura y sigue esperando que alcance el final para volver al punto de retorno y vaciar la pila del valor de retorno como esto ya no va a ocurrir se esta perdiendo espacio de pila con cada situacion de este tipo Tambien podria darse el caso si algun lenguaje olvida aportar solucion que al ir entregando desde la pila los sucesivos retornos se apunte a un lugar diferente de la que el programador esperaba por la cascada de entradas fue una y la cascada de salidas debiendo ser en orden inversa conserva una salida que nunca se va a producir falsificando con ello todas las devoluciones anteriores a esa que se ha quedado perdida por la instruccion goto Un modo en que algunos lenguajes solventan este problema es utilizando una pila exclusivamente local y eliminarla cuando se sale del procedimiento local en dicho caso la direccion de retorno se guarda en una pila de ambito mayor Si hay punteros remanentes en la pila local no devueltos no produciran errores en cascada hacia atras En situaciones asi es dificil seguir la pista de saltos esperada respecto de la que el programador pretendiera hacer si no se comporta como el esperaba Tambien de este modo es posible hacer que el codigo se comporte de una forma que el lenguaje no tenia previsto en su diseno y aprovechar con ello una posible situacion eficiente para realizar determinadas tareas Adicionalmente para solventar los posibles problemas que el inadecuado uso de GOTO pueda originar los lenguajes de alto nivel y que utilizan programacion mediante bloques y modulos bien definidos y aislados no permiten sobre GOTO mas que operar dentro del bloque o modulo donde se aloja Un caso tipico son las modernas funciones FUNCTION PROPERTY etc donde si bien un GOTO puede aparecer no puede direccionar a un punto dentro de otra FUNCTION No confundir este aislamiento con encapsulamiento aunque la idea es la misma GOTO envia el flujo dentro de una estructura de control Editar Sucede de otra forma cuando un salto por GOTO nos introduce dentro de una estructura de control Si hay instrucciones tras la etiqueta a la que se salta estas se ejecutan correctamente pero al llegar a una instruccion del final si la pila esta vacia cuando la estructura de control requiere un puntero de retorno ocurre un error que segun el lenguaje varia y si la pila no esta vacia salta a la direccion que senala el ultimo puntero en la pila puede considerarse un error si no era lo que perseguia el programador toda vez que dicho puntero no fue almacenado por dicha estructura decontrol en la que se halla sino por la previa Esto solo sucede en aquellas estructuras de control que guardan algun puntero de retorno en la pila por ejemplo nunca ocurrira un error dentro de una estructura IF THEN ni dentro de una estructura SELECT CASE Switch ni DO LOOP ya que dichas estructuras al no tener al final un punto de retorno no necesitan almacenar en la pila dicho punto de retorno Normalmente es el caso que en los lenguajes la ejecucion de la sentencia GOTO no conlleva aparejado comprobar si salta dentro de una estructura de control ya que en principio no debe generar errores aunque tenga un puntero de retorno siempre que este puntero este localizado en la sentencia de salida en vez de en la pila Se detallan comentados 3 casos comunes Caso de estructura de control donde el puntero de retorno se almacena en la sentencia final este suele ser DO LOOP loop es equivalente a un GOTO DO En una seccion del articulo mas adelante se provee una implementacion de la estructura de control DO LOOP usando GOTO que ayudara a entender este caso En este caso por tanto saltar dentro de una estructura DO LOOP no proporcionara un error si se llega a la sentencia final ver seccion anterior El puntero de retorno de esta estructura siempre apunta al principio de la estructura es por esto que no necesita mantenerlo en la pila t resulta suficiente con dejarlo en la sentencia final Otro caso de estructura de control que el puntero de retorno se almacena en la sentencia final pero que si da errores un caso de este tipo suele ser FOR NEXT La estructura FOR se compone de 3 secciones operativas en la primera se inicializan los valores del bucle en la 2ª se produce el incremento de los valores que controlan el bucle y en la 3ª seccion esta el bloque de sentencias que se ha de repetir Si una sentencia GOTO lleva el flujo dentro de un bucle FOR cuando se alcanza la sentencia NEXT esta sabe localizar el retorno hacia la 2ª seccion en este sentido se comporta como DO LOOP NEXT equivale a GOTO 2ª Seccion pero al tratar de incrementar el bucle descubre que las variables que necesita el bucle no han sido inicializadas por lo que produce un error de forma indirecta Un bucle FOR utiliza 4 variables internamente para su propio control una variable contador que es la que se ira incrementando 3 variables o constantes que asigna el valor inicial final y cantidad de incremento respectivamente Caso de estructura de control que el puntero de retorno se almacena en la pila El caso de este tipo suele ser GOSUB Cada vez que se ejecuta una sentencia GOSUB FUNCTION etc se guarda en la pila la direccion de origen y cada vez que se ejecuta la sentencia RETURN se salta a la ultima direccion contenida en la pila es decir no existe un par asociado GOSUB RETURN Vease GOSUB para mas detalles Este caso es el mas proclive a que ofrezca un comportamiento dificil de seguir GOTO envia el flujo desde dentro de una estructura de control a otro punto dentro Editar En cualquier caso puede haber innumerables sentencias GOTO dentro de una estructura de control y recorrerla de forma arbitraria sin que genere ningun error excepto que se alcance ejecute su turno una sentencia de retorno que requiera un puntero de retorno en la pila que no exista como ya se comento si existen valores en la pila puede darse errores o no sobre la base de si esa es la idea que perseguia el programador o no ya que retornara el ultimo puntero que contenga la pila Comparacion entre GOTO y otras instrucciones de control del flujo EditarGOTO es incondicional es decir ordena el salto de ejecucion del programa a una direccion concreta El salto se solicita porque se requiere que la ejecucion continue desde alli La problematica de esto resulta en que no resulta evidente el orden de ejecucion Como se podra apreciar en las sucesivas comparaciones GOTO puede implementar todas las estructuras de control su controversia no se deduce de su versatilidad si no de la enajenacion de claridad en que resulta su uso Las estructuras de control de lenguajes de alto nivel estan realizadas usando GOTO tipicamente JMP y sus variantes en ensamblador Comparacion con GOSUB Editar Al igual que GOTO GOSUB tampoco acepta en la mayoria de lenguajes que se utiliza un salto a una direccion que no sea una constante es decir no acepta valores desde variables sino solo desde constantes lo que en cierto modo limita la casuistica de errores en que pudiera derivar Una diferencia sustancial se establece con las instrucciones GOSUB saltar a subrutina la diferencia esencial es que gosub tras saltar a la instruccion indicada ejecuta un numero determinado de instrucciones hasta que encuentra una instruccion RETURN que le obliga volver a la siguiente instruccion que viene a continuacion de la instruccion GOSUB GOSUB por tanto puede entenderse como utilizar 2 gotos el que salta a la instruccion indicada y el que retorna a la posicion ultima que se guarda en la pila Es por esto que una instruccion GOTO no guarda el origen de procedencia en la pila GOSUB debe necesariamente antes de proceder con el salto guardar en la pila la direccion desde la que salta para que a su regreso el contador de programa incremente en una unidad GOSUB por tanto delimita no solo el inicio de un grupo de instrucciones sino que tambien queda claro su final GOSUB requiere una instruccion de retorno aunque nada impide colocar varias instrucciones de forma condicionada En consecuencia a estas consideraciones GOSUB ofrece un paso mas alla el control del flujo que GOTO por si solo no permite no obstante GOTO puede emular a GOSUB pues puede alli donde hubiera un RETURN remplazarse con un GOTO a la siguiente instruccion del GOTO de origen Implementacion de GOSUB usando GOTO Editar Como puede deducirse en el ejemplo a continuacion ambos hacen lo mismo y la diferencia radica en que usando GOTO el programador debe controlar todos los saltos vease lineas GOTO x3 para regresar al punto de partida GOSUB en cambio hace esto de forma automatica transparente para el programador que se desentiende de que linea o que direccion ha de tener el retorno ya que este valor se guarda en la pila en el momento de procesar la sentencia GOSUB Nota previas para entender el ejemplo instr representan cualquier instruccion representa un comentario en la linea a partir de ahi El numero que le sigue representa la continuidad en la posicion de memoria que solo sirve al efecto de comprender mejor el ejemplo Si este numero va entre parentesis indica una posicion relativa respecto de este ejemplo de rutina usando GOSUB Editar A 5 x 1 instr x instr x 1 GOSUB 400 instr x 2 instr x 3 400 instr x instr 400 1 instr 400 2 Si A es 2 luego instr 400 4 RETURN En otro caso instr 400 7 instr 400 8 Fin casos RETURNejemplo de emulacion de GOSUB usando GOTO Editar instr x instr x 1 GOTO 400 instr x 2 X3 instr x 3 400 instr x instr 400 1 instr 400 2 Si A es 2 luego instr 400 4 GOTO x3 En otro caso instr 400 7 instr 400 8 Fin casos GOTO x3Comparacion con IF THEN ELSE Editar Como ya se ha indicado el salto de GOTO es incondicional al llegar a ese punto se ejecuta y eso es todo a un posible lector no le queda claro cual es la razon de salto solo sabe a ciencia cierta que la ejecucion continua en el punto indicado y nada mas para comprender mejor que sucede necesita estudiar con detenimiento las condiciones previas lo que supone una ardua tarea especialmente cuando se busca codigo optimizado para velocidad ya que entonces el mismo puede resultar mas dificil de entender La principal diferencia entre GOTO y la sentencia IF THEN ELSE es que GOTO puede basar su salto en los condicionantes que se dan previamente lo que obliga en la toma de decisiones a utilizar varias sentencias GOTO que lo hace aun mas complejo de analizar La sentencia IF asocia el salto a un cumulo de sucesos concretos puede haber una o varias condiones cuya evaluacion conjunta se evalua como verdadero o falso de modo que es posible y facil entender que el salto se produce solo si no se cumple la condicion ejecutandose si se cumple no se salta se continua con las siguientes instrucciones y al final de las mismas salta hasta el final de todo el bloque que forman la sentencia y las instrucciones asociadas a sendas condiciones Para comprender correctamente como se produce esto es necesario distinguir la sentencia de salto condicional IF que es de alto nivel con las instrucciones ensamblador de salto condicional saltar si cero saltar si no cero etc Son estas ultimas quienes determinan si el salto se produce dadas las condiciones Comparacion con FOR NEXT Editar Comparacion con DO LOOP WHILE Editar Comparacion con FUNCION EditarEjemplos EditarPascal Editar En Pascal donde se deben declarar las etiquetas con la palabra reservada LABEL Program UsoGOTO input output LABEL Salto BEGIN Writeln Como estamos antes del GOTO esto saldra en pantalla GOTO Salto Writeln Esto no saldra en pantalla Salto Writeln Se efectuo una ruptura en el flujo debido a la sentencia GOTO END Pauscal Editar En Pauscal es posible usar la instruccion IrHacia GoTo en espanol declarando una etiqueta y estableciendola como parametro Var i Entero Etiqueta i i 1 IrHacia Etiqueta C Editar En Lenguaje de programacion C se declaran las etiquetas con dos puntos al final static void main etiqueta La etiqueta goto etiqueta Ir a la etiqueta Basic Editar En BASIC las etiquetas se sentencian igual que en C con dos puntos al final PRINT Prueba de GOTO en QBASIC GOTO prueba PRINT Esto no se ve porque hemos saltado a la etiqueta llamada prueba prueba PRINT GOTO realizado correctamente En algunas variantes de BASIC como por ejemplo Just BASIC o Liberty BASIC se usa y para remarcar etiquetas PRINT Prueba de GOTO en QBASIC GOTO prueba PRINT Esto no se ve porque hemos saltado a la etiqueta llamada prueba prueba PRINT GOTO realizado correctamente Ensamblador Editar En ensamblador se emplean instrucciones similares En el caso de x86 la instruccion es jmp Programa para GNU Linux Ensamblar con cc jmp S o jmp Muestra Comenzando bucle y seguidamente entra en un bucle mostrando Hola mundo a cada iteracion section rodata msg1 string Hola mundo msg2 string Comenzando bucle section text globl main main movl msg2 esp call puts etiqueta movl msg esp call puts jmp etiqueta end Vease tambien EditarEstructuras de control Bucle Bucle for Bucle while Bucle repetir Ciclo infinito Codigo spaghetti Teorema del programa estructurado Programacion estructurada Lenguaje de programacionBibliografia Editar Peter Bishop Programacion avanzada en BASIC Ediciones Anaya Multimedia ano 1990 ISBN 978 84 7614 013 0 pagina 86 Una vez escrita la parte del programa correspondiente a un bucle es muy tentador aprovechar algunas o todas las instrucciones contenidas en esa parte para otros fines lo que obliga a utilizar bifurcaciones para acceder al bucle desde otros puntos del programa lo que se haria con GOTOs Esa tentacion debe resistirse a toda costa Ramificar un programa hacia el interior de un bucle es una costumbre completamente desaconsejable Peter Bishop Programacion avanzada en BASIC Ediciones Anaya Multimedia ano 1990 ISBN 978 84 7614 013 0 pagina 86 Otra cosa es crear una bifurcacion para salir de un bucle situacion que se plantea cuando la terminacion del mismo depende de mas de una sola condicion Una de ellas es la llegada del contador a su valor final y la otra supone alguna verificacion realizada dentro del propio bucle no es recomendable saltar directamente al exterior de un bucle Lo mejor es pasar el contador a su valor final y saltar hasta el fin del bucle Datos Q750997Obtenido de https es wikipedia org w index php title GOTO amp oldid 128770545, wikipedia, wiki, leyendo, leer, libro, biblioteca,

español

, española, descargar, gratis, descargar gratis, mp3, video, mp4, 3gp, jpg, jpeg, gif, png, imagen, música, canción, película, libro, juego, juegos