Goto

Goto es una sentencia que te permite cambiar el flujo de ejecución de un programa de formas que probablemente no deberías de todos modos. En este vídeo te explico cómo crear etiquetas, cómo insertar un goto, por qué tal vez no sea lo óptimo, y algunas soluciones al respecto.

La sentencia goto en C es una herramienta que nos permite saltar a distintas partes del código mediante etiquetas, pero su uso rompe con la estructura predecible y ordenada que caracteriza a la programación estructurada. Aunque muchos programadores y educadores la consideran una mala práctica y desaconsejan su uso, entender cómo funciona es fundamental para evitar errores graves y para comprender ciertos casos especiales donde puede ser útil.

En C, podemos crear etiquetas simplemente escribiendo un identificador seguido de dos puntos, por ejemplo zona_interesante:. Esto marca una posición en el código a la que podemos saltar con un goto zona_interesante;. Sin embargo, cuando usamos goto, interrumpimos el flujo normal del programa. Por ejemplo, si estamos dentro de un bucle y ejecutamos un goto que salta fuera de ese bucle, dejamos de ejecutar el resto de las iteraciones y el control de flujo se vuelve impredecible. Esto hace que el código sea más difícil de leer y mantener, ya que quien lo lea tendrá que buscar a dónde salta el programa y por qué, rompiendo la armonía y la claridad que aporta la programación estructurada.

Además, el goto es bidireccional: podemos saltar hacia adelante o hacia atrás en el código. Esto puede generar bucles o saltos inesperados que complican aún más el seguimiento del programa. Por ejemplo, si dentro de un bucle hacemos un salto hacia una etiqueta que está antes del bucle, podemos provocar que el programa entre en un ciclo caótico y difícil de entender.

Veamos un ejemplo sencillo para ilustrar cómo funciona el goto y sus efectos:

#include <stdio.h>

int main() {
    int i, j = 0;

    while (j < 500) {
        for (i = 1; i <= 10; i++) {
            j = j + i;
            printf("%d\n", j);

            if (j > 300) {
                goto zona_interesante;
            }
        }
    }

    printf("Hemos alcanzado el valor j es igual a %d\n", j);
    return 0;

zona_interesante:
    printf("Estamos en la zona interesante\n");
    return 0;
}

En este código, cuando j supera 300, saltamos directamente a la etiqueta zona_interesante, interrumpiendo el bucle y el flujo normal del programa. Esto puede ser confuso porque el salto rompe la secuencia lógica que esperaríamos en un programa estructurado.

Una alternativa mucho más clara y segura es usar funciones y return para controlar el flujo. Por ejemplo, en lugar de usar goto para salir de un bucle o función, podemos encapsular la lógica en una función y usar return para salir anticipadamente cuando se cumpla una condición. Esto mantiene la estructura del programa clara y predecible.

Por ejemplo:

#include <stdio.h>

int bucle() {
    int i, j = 0;

    while (j < 500) {
        for (i = 1; i <= 10; i++) {
            j = j + i;
            printf("%d\n", j);

            if (j > 300) {
                return j; // Salimos de la función cuando j supera 300
            }
        }
    }

    return j;
}

int main() {
    int resultado = bucle();
    printf("Hemos alcanzado el valor j es igual a %d\n", resultado);
    return 0;
}

Aquí, el uso de return nos permite salir de la función bucle cuando j supera 300, sin necesidad de saltos arbitrarios en el código. Esto facilita la lectura y el mantenimiento del programa.

Aunque el goto es generalmente desaconsejado, en ciertos contextos de programación de bajo nivel, como en controladores de dispositivos o kernels, puede ser útil para optimizar el código o para manejar errores de manera eficiente. Sin embargo, para la mayoría de los casos en programación de aplicaciones, es preferible evitarlo y optar por estructuras más claras y seguras.

En definitiva, el goto rompe la armonía y la previsibilidad del flujo de ejecución en C, y aunque es importante conocer su funcionamiento para no usarlo incorrectamente, debemos buscar alternativas que mantengan nuestro código limpio y fácil de entender.

Lista de reproducción
  1. 1
    Instalar CodeBlocks
    15 minutos
  2. 2
    Funciones y hola mundo
    17 minutos
  3. 3
    Variables y tipos de datos
    17 minutos
  4. 4
    Condicionales y operadores lógicos
    16 minutos
  5. 5
    Bucles
    11 minutos
  6. 6
    Punteros
    12 minutos
  7. 7
    Arrays
    14 minutos
  8. 8
    Estructuras
    12 minutos
  9. 9
    Otras construcciones de C
    9 minutos
  10. 10
    Memoria dinámica
    8 minutos
  11. 11
    El preprocesador (parte 1)
    10 minutos
  12. 12
    El preprocesador (parte 2)
    9 minutos
  13. 13
    Archivos de cabecera y múltiples .c (parte 1)
    8 minutos
  14. 14
    Archivos de cabecera y múltiples .c (parte 2)
    9 minutos
  15. 15
    C desde la línea de comandos (parte 1)
    8 minutos
  16. 16
    C desde la línea de comandos (parte 2)
    9 minutos
  17. 17
    Break y continue
    10 minutos
  18. 18
    Goto
    13 minutos
  19. 19
    Manipulación de bits
    15 minutos
  20. 20
    Máscaras de bit
    19 minutos
  21. 21
    Archivos (1): fopen y fclose
    13 minutos
  22. 22
    Archivos (2): leer con fgetc
    9 minutos
  23. 23
    Archivos (3): fseek y ftell
    11 minutos
  24. 24
    Archivos (4): leer con fgets
    9 minutos
  25. 25
    Archivos (5): fputc y fputs
    7 minutos
  26. 26
    Archivos (6): volcar en archivos con fwrite
    10 minutos
  27. 27
    Archivos (7): fread, fwrite y los arrays
    10 minutos
  28. 28
    Archivos (8): entrada estándar y salida estándar
    9 minutos
  29. 29
    Archivos (9): buffers
    14 minutos
  30. 30
    Archivos (y 10): otras funciones útiles con archivos
    5 minutos
  31. 31
    printf (1)
    18 minutos
  32. 32
    printf (parte 2)
    12 minutos
  33. 33
    scanf (parte 1)
    17 minutos
  34. 34
    scanf (parte 2)
    17 minutos
  35. 35
    fprintf, sprintf y snprintf
    8 minutos
  36. 36
    Tipos de datos opacos
    13 minutos
  37. 37
    Bibliotecas estáticas
    13 minutos
  38. 38
    Bibliotecas dinámicas
    15 minutos
  39. 39
    Más flags: i mayúscula (include), wall, werror, pedantic...
    12 minutos
  40. 40
    pkg-config
    12 minutos
  41. 41
    Make
    17 minutos
  42. 42
    GDB
    21 minutos
  43. 43
    Variables globales
    6 minutos
  44. 44
    extern
    9 minutos
  45. 45
    Funciones variádicas
    12 minutos
  46. 46
    El optimizador de GCC y la opción -O
    12 minutos
  47. 47
    Volatile
    6 minutos