switch significado loop gotoxy for espaƱol dev comando c goto

significado - mientras que(1).. rompe en lugar de ir a goto



loop en c (13)

"break" entiende la semántica del ámbito de bloque, mientras que "goto" no le tiene en cuenta. En otras palabras, "while-break" puede traducirse a lenguajes funcionales como Lisp con recursión de cola, "goto" no puede.

Encontré el siguiente código en un programa en C:

while (1) { do_something(); if (was_an_error()) break; do_something_else(); if (was_an_error()) break; [...] break; } [cleanup code]

Aquí while(1) se usa como emulación local de "finalmente". También puedes escribir esto usando goto s:

do_something() if (was_an_error()) goto out; do_something_else() if (was_an_error()) goto out; [...] out: [cleanup code]

Pensé que la solución de goto es una expresión habitual. He visto varias apariciones de este idioma en las fuentes del núcleo y también se menciona en el libro "Lectura de códigos" de Diomidis Spinellis.

Mi pregunta es: ¿Qué solución es mejor? ¿Hay alguna razón específica para usar la solución while(1) ?

La pregunta 943826 no responde mi pregunta.


"do while" y "goto out" son diferentes en estas áreas:

1. inicialización de variables locales

void foo(bool t = false) { if (t) { goto DONE; } int a = 10; // error : Goto bypass local variable''s initialization cout << "a=" << a << "/n"; DONE: }

Está bien inicializar variables locales in situ en do ... while (0) block.

void bar(bool t = false) { do{ if (t) { break; } int a = 10; // fine cout << "a=" << a << "/n"; } while (0); }

2 diferencias para macros. "Hacer mientras" es un poco mejor. "goto DONE" en una macro no es el caso. Si el código de salida es más complicado, veamos así:

err = some_func(...); if (err) { register_err(err, __LINE__, __FUNC__); #if defined (_DEBUG) do_some_debug(err) #endif break; }

y si escribe este código una y otra vez, probablemente los coloque en una Macro.

#define QUIT_IF(err) / if (err) / { / register_err(err, __LINE__, __FUNC__); / DO_SOME_DEBUG(err) / break; // awful to put break in macro, but even worse to put "goto DONE" in macro. / }

Y el código se convierte en:

do { initial(); do { err = do_step1(); QUIT_IF(err); err = do_step2(); QUIT_IF(err); err = do_step3(); QUIT_IF(err); .... } while (0); if (err) { // harder for "goto DONE" to get here while still using macro. err = do_something_else(); } QUIT_IF(err); ..... } while (0);

3.do ... while (0) maneja diferentes niveles de salida con la misma macro. El código se muestra arriba. goto ... no es el caso de Macro porque necesita diferentes etiquetas para diferentes niveles.

Al decir eso, no me gustan los dos. Prefiero usar el método de excepción. Si no se permite la excepción, entonces uso "do ... while (0)", ya que todo el bloque está sangrado, en realidad es más fácil de leer que el estilo "goto DONE".


Úsalo si no puedes usar goto por cualquier razón.

  • Prohibido en las convenciones de tu proyecto.
  • prohibido por tu herramienta de pelusas

También creo que ese es también uno de los casos en que las macros no son malas:

#define DO_ONCE for (int _once_dummy = 0; _once_dummy < 1; _once_dummy++)


¿Por qué no usar una serie de declaraciones if ? Normalmente lo escribo de esta manera, ya que lo encuentro mucho más claro que un bucle:

bool ok = true; do_something(); if (was_an_error()) ok = false; if (ok) { do_something_else(); if (was_an_error()) ok = false; } if (ok) { do_something_else_again(); if (was_an_error()) ok = false; } [...] [Cleanup code]

Además, si está trabajando con estrictos estándares de codificación, sí es probable que goto esté prohibido, pero a menudo se break y continue por lo que el bucle no es necesariamente una solución para eso.


Aunque el uso de goto se desaconseja generalmente, algunas situaciones raras como la suya son lugares donde las mejores prácticas no son las mejores.

Entonces, si goto hace el código más claro, lo usaría. usar un bucle while (verdadero) para emular goto es algo antinatural. Lo que realmente necesitas es un goto!


Creo que este uso (para la gestión de recursos) de goto está bien.


La revocación aparentemente universal de GOTO se debe en gran parte a la carta de Edsger Dijkstra "Ir a la declaración considerada perjudicial".

Si estás decidido a no usar goto, algo como

do { ... while(0);

es probablemente más seguro que while (1) {...}, ya que garantiza que no realizarás bucles involuntariamente (y si haces un bucle involuntariamente, mientras que (1) probablemente haces un bucle infinitamente).

La única ventaja que tiene (ab) usar do / break / while o while / break para este propósito sobre goto es que se le garantiza que no estará saltando por encima de la construcción: se puede usar goto para saltar a una etiqueta antes dentro de la misma función.

La desventaja que do / break / while etc. tiene sobre goto es que está limitado a un punto de salida (inmediatamente después del bucle). En algunos casos, es posible que necesite una limpieza por etapas: por ejemplo, cuando abre un manejador de archivos, haga un malloc de memoria, lea del archivo ... si la lectura falla, necesita limpiar el malloc. Si el malloc falla, no es necesario que lo limpie, pero sí necesita limpiar el identificador de archivo. Con goto, puede tener una etiqueta por etapa de limpieza y saltar exactamente al punto correcto dependiendo de donde ocurrió el error.

En mi opinión, evitar ciegamente a GOTO debido al odio predominante es más perjudicial que razonar con cuidado un caso para su uso caso por caso. Una regla de oro que uso es "¿el kernel de Linux lo hace? Si es así, no puede ser tan malo". Reemplace el kernel de Linux con cualquier otro buen ejemplo de ingeniería de software moderna.


Me gusta el enfoque de while (1). Yo lo uso yo mismo. Especialmente, cuando el bucle puede repetirse al continuar, por ejemplo, cuando un elemento se procesa dentro de dicho bucle, y se realiza en varios enfoques.


Normalmente, los GOTO se consideran malos, pero en algunos lugares donde solo hay Forward Jumps a través de GOTO, no son tan malos. Las personas evitan la plaga como GOTO, pero un uso bien pensado de GOTO es a veces una mejor solución IMHO.


Nunca use un bucle de condición con una condición permanentemente verdadera. Dado que la condición es siempre cierta, ¿por qué usar un bucle condicional?

Las condiciones permanentemente verdaderas están representadas más directamente por un goto.


Poner el código en una función separada y utilizar return para salir antes es otra forma de hacerlo, con el beneficio de una fácil integración de un código de retorno que indica la naturaleza de la falla.


Sé que mi estilo no es lo más genial posible, pero lo prefiero porque no necesita ninguna construcción especial y es conciso y no demasiado difícil de entender:

error = (!error) && do_something1(); error = (!error) && do_something2(); error = (!error) && do_something3(); // Cleanup code


Si bien el uso de "goto" para situaciones de manejo de errores es bastante común, prefiero la solución "while" (o "do while"). En el caso de "goto", hay muchas menos cosas que el compilador puede garantizar. Si crea un error tipográfico en el nombre de la etiqueta, el compilador no puede ayudarlo allí. Si alguien usa otro goto para otra etiqueta en ese bloque, es muy probable que no se llame al código de limpieza. Cuando utiliza las construcciones de control de flujo más estructuradas, siempre se le garantiza qué código se ejecutará una vez que finalice el ciclo.