goto
statement
Transfiere el control incondicionalmente.
Se utiliza cuando de otro modo es imposible transferir el control a la ubicación deseada utilizando otras sentencias.
Contenidos |
Sintaxis
attr
(opcional)
goto
etiqueta
;
|
|||||||||
Explicación
La instrucción goto transfiere el control a la ubicación especificada por la etiqueta . La instrucción goto debe estar en la misma función que la etiqueta a la que se refiere, y puede aparecer antes o después de la etiqueta.
Si la transferencia de control sale del ámbito de cualquier variable automática (por ejemplo, saltando hacia atrás a un punto anterior a las declaraciones de dichas variables o saltando hacia adelante fuera de una sentencia compuesta donde las variables tienen ámbito), los destructores son llamados para todas las variables cuyo ámbito fue abandonado, en el orden opuesto al orden de su construcción.
La declaración goto no puede transferir el control hacia una declaración de control de flujo limitado , pero puede transferir el control fuera de una declaración de control de flujo limitado (se siguen las reglas mencionadas anteriormente respecto a las variables automáticas en alcance).
Si la transferencia de control entra en el ámbito de cualquier variable automática (por ejemplo, saltando hacia adelante sobre una declaración), el programa está mal formado (no puede compilarse), a menos que todas las variables cuyo ámbito se ingresa tengan los siguientes tipos:
- tipos escalares declarados sin inicializadores
- tipos de clase con constructores por defecto triviales y destructores triviales declarados sin inicializadores
- versiones calificadas cv de uno de los anteriores
- arrays de uno de los anteriores
(Nota: las mismas reglas se aplican a todas las formas de transferencia de control)
Notas
En el lenguaje de programación C, la sentencia goto tiene menos restricciones y puede entrar en el ámbito de cualquier variable excepto arreglos de longitud variable o punteros modificables variablemente.
Palabras clave
Ejemplo
#include <iostream> struct Object { // destructor no trivial ~Object() { std::cout << 'd'; } }; struct Trivial { double d1; double d2; }; // ctor y dtor triviales int main() { int a = 10; // bucle usando goto label: Object obj; std::cout << a << ' '; a -= 2; if (a != 0) goto label; // salta fuera del ámbito de obj, llama al destructor de obj std::cout << '\n'; // goto puede usarse para salir eficientemente de bucles multinivel (anidados) for (int x = 0; x < 3; ++x) for (int y = 0; y < 3; ++y) { std::cout << '(' << x << ',' << y << ") " << '\n'; if (x + y >= 3) goto endloop; } endloop: std::cout << '\n'; goto label2; // salta al ámbito de n y t [[maybe_unused]] int n; // sin inicializador [[maybe_unused]] Trivial t; // ctor/dtor trivial, sin inicializador // int x = 1; // error: tiene inicializador // Object obj2; // error: destructor no trivial label2: { Object obj3; goto label3; // salta hacia adelante, fuera del ámbito de obj3 } label3: std::cout << '\n'; }
Salida:
10 d8 d6 d4 d2 (0,0) (0,1) (0,2) (1,0) (1,1) (1,2) d d
Véase también
|
Documentación de C
para
goto
|
Enlaces externos
|
El popular ensayo de Edsger W. Dijkstra, “Goto Considered Harmful” (originalmente, en "Letter to Communications of the ACM (CACM)", vol. 11 #3, marzo de 1968, pp. 147-148.), presenta un análisis de los muchos problemas sutiles que el uso descuidado de esta palabra clave puede introducir. |