do {…} while (falso)

125

Estaba mirando un código por un individuo y noté que parece tener un patrón en sus funciones:

<return-type> function(<params>)
{
 <initialization>

 do
 {
   <main code for function>
 }
 while(false);

 <tidy-up & return>
}

No está mal , es más peculiar (el código real es bastante ordenado y no sorprende). No es algo que haya visto antes y me preguntaba si alguien puede pensar en alguna lógica detrás de él, ¿quizás en un idioma diferente?

Señor chico
fuente
2
¿Has intentado cambiarlo a la versión "normal" y ver si aún se compila? Si no se compila cuando se escribe normalmente, el error del compilador podría dar una pista de por qué se hizo esto.
Mark Byers
11
¿Por qué no preguntar al "individuo" en lugar de pedirnos suposiciones sobre su intención?
1
Tal vez su profesor requirió que usara do...while()y ha usado ese código como plantilla de función desde entonces.
Hogan
66
@Neil ... Quiero evitar parecer tonto cuando lo enfrento y él explica el uso súper avanzado de C ++ en el que nunca pensé.
Sr. Boy
66
Parece que ya hay bastantes respuestas diferentes, ¿puede preguntarle al autor original cuáles fueron sus intenciones y publicar de nuevo?
nevets1219

Respuestas:

175

Puedes breaksalir de do{...}while(false).

Thomas Eding
fuente
95
+1 porque esa es probablemente la intención del código, pero hacer algo como esto es solo un goto disfrazado idiota Si crees que un goto es la herramienta adecuada para el trabajo, entonces solo debes usar un # $ (* # @ goto.
dsimcha
55
Es más que un goto disfrazado. Es un goto restringido (estructurado).
Thomas Eding
19
¿De qué manera está "restringido"? Solo saltar hacia adelante no es una "restricción". Un goto es un goto, y vestirse uno para que parezca que no es uno es peor que simplemente usar un goto en primer lugar.
Anon
44
@Anon .: Saltar hacia adelante es una restricción para un goto, y saltar es definitivamente una restricción. El verdadero problema con los gotos es el código de espagueti, y un salto hacia adelante y hacia afuera limita enormemente.
David Thornley
33
Un bucle real no es semánticamente un goto. Un condicional no es semánticamente un goto. "Ir al final de la función y hacer el código de limpieza" es semánticamente un goto. Use gotos cuando se aplique la semántica, no disfrace algo semánticamente diferente porque les tiene miedo.
Anon
126

Mucha gente señala que a menudo se usa con break como una forma incómoda de escribir "goto". Eso probablemente sea cierto si está escrito directamente en la función.

En una macro, OTOH, do { something; } while (false)es una forma conveniente de FORZAR un punto y coma después de la invocación de la macro, absolutamente ningún otro token puede seguir.

Y otra posibilidad es que haya una vez un bucle allí o se anticipe que se agregará iteración en el futuro (por ejemplo, en el desarrollo basado en pruebas, no fue necesaria la iteración para pasar las pruebas, pero lógicamente tendría sentido hacerlo allí si la función debía ser algo más general de lo que se requiere actualmente)

Ben Voigt
fuente
18
+1 por mencionar la utilidad de esto en macros; ¡Me sorprende que nadie más lo haya mencionado!
Nick Meyer
77
Sí, lo macro es en realidad un uso perfectamente válido de esto. Por supuesto, fuera de las macros, es una tontería ...;)
jalf
12
No es extraño, es útil, porque es un Scoped Goto - esto significa que todas las variables se declaran en el bucle hacer destruidos, mientras que el Goto no hace eso.
Ana Betts
9
@Paul: Nada le impide agregar llaves alrededor de un conjunto de declaraciones para forzar este comportamiento con goto.
erikkallen
55
@Paul: goto fuera de un bloque definitivamente causa que las variables locales se destruyan en C ++, igual que break. Y en las variables C no se destruyen realmente, su espacio de pila simplemente se recupera.
Ben Voigt
25

El descanso como goto es probablemente la respuesta, pero propondré otra idea.

Tal vez quería tener variables definidas localmente y usó esta construcción para obtener un nuevo alcance.

Recuerde que si bien C ++ reciente permite {...}cualquier lugar, este no siempre fue el caso.

Hogan
fuente
30
Podría haber usado llaves en ese caso.
Nemanja Trifunovic
2
@Nemanja, te sorprendería saber cuántos desarrolladores no lo saben y probar algo relacionado con lo que sugiere Hogan
Polaris878,
8
@Polaris @Nemanja, no fue hasta que estuve programando en C / C ++ como 4 años que descubrí que puedes crear un nuevo alcance local en {} cualquier lugar ... Esto es especialmente útil en el switch-casecódigo
Earlz
1
@Nemanja: No sé exactamente cuándo, pero estoy seguro de que en {...}cualquier lugar hay un desarrollo más moderno en C ++ (recuerde que el primer C ++ que utilicé se implementó con un preprocesador y eso no permitió este uso moderno). Quizás el autor era simplemente de la vieja escuela.
Hogan
2
¿Cuándo no permitió llaves en todas partes? Comencé a programar como hace 15 años, y estaba permitido entonces (tanto en mi libro de texto como en cada compilador que probé).
erikkallen
20

He visto que se usa como un patrón útil cuando hay muchos puntos de salida potenciales para la función, pero siempre se requiere el mismo código de limpieza independientemente de cómo salga la función.

Puede hacer que un árbol cansador if / else-if sea mucho más fácil de leer, simplemente teniendo que romperse cada vez que se alcanza un punto de salida, con el resto de la lógica en línea después.

Este patrón también es útil en idiomas que no tienen una instrucción goto. Quizás ahí es donde el programador original aprendió el patrón.

Cameron
fuente
15
Luego, use un goto honesto y directo en lugar de un goto apenas disfrazado.
dsimcha
44
Me gusta más así. Es fácil de leer y no lleva el estigma de un goto.
Cameron
8
Los gotos son perfectamente fáciles de leer si se usan con moderación y localmente. Obtuvieron su estigma desde atrás cuando eran la forma principal de control de flujo y saltaban a través de cientos de líneas.
dsimcha
13
No usar goto debido a un "estigma" es una señal segura de la programación de culto de carga.
Anon
66
Sin mencionar que una gran cantidad de código de limpieza es un mal olor. Siendo C ++, el código de limpieza normalmente debería estar en los destructores llamados durante el procesamiento RAII.
David Thornley
12

He visto un código así para que pueda usarlo breakcomo una gotoespecie de.

Brian Young
fuente
10

Esto es solo una perversión de whileobtener la semántica de goto tidy-upsin usar la palabra goto.

Es de mal gusto ya que al usar otros circuitos en el interior del exterior de whilela breaksvuelven ambiguos para el lector. "¿Se supone que esto tiene que salir? ¿O está destinado solo a salir del circuito interno?"

John Knoeller
fuente
10

Creo que es más conveniente escribir en breaklugar de goto end. Ni siquiera tiene que pensar en un nombre para la etiqueta que aclare la intención: no desea saltar a una etiqueta con un nombre específico. Quieres salir de aquí.

También es probable que necesite los frenos de todos modos. Entonces esta es la do{...}while(false);versión:

do {
   // code
   if (condition) break; // or continue
   // more code
} while(false);

Y esta es la forma en que tendrías que expresarlo si quisieras usar goto:

{
   // code
   if (condition) goto end;
   // more code
}
end:

Creo que el significado de la primera versión es mucho más fácil de entender. También es más fácil de escribir, más fácil de extender, más fácil de traducir a un idioma que no es compatible goto, etc.


La preocupación más frecuentemente mencionada sobre el uso de breakes que está muy mal disfrazada goto. Pero en realidad breaktiene más parecido a return: Ambas instrucciones saltan de un bloque de código que está más o menos estructurado en comparación con goto. Sin embargo, ambas instrucciones permiten múltiples puntos de salida en un bloque de código que a veces puede ser confuso. Después de todo, trataría de buscar la solución más clara, cualquiera que sea la situación específica.

Robert
fuente
Ah, me di cuenta de que no entendía la pregunta por completo antes de responder. Pensé que se trataba del uso de do{ ... }while(false);en general. Pero en realidad se trata de usarlo para emular algún tipo de try{ ... }finally{ ... }.
Robert
Bonita observación del paralelo entre descanso y retorno en lugar de ir a. De acuerdo en que la solución más clara es la mejor. En muchos casos, probablemente sea más claro encapsular código como este en su propia función separada que usa return en lugar de break y luego realiza la limpieza en la función de llamada.
persiflage
7

Este truco lo usan los programadores que son demasiado tímidos para usar un gotocódigo explícito . El autor del código anterior quería tener la capacidad de saltar directamente al punto de "limpieza y retorno" desde la mitad del código. Pero no querían usar una etiqueta explícita goto. En cambio, pueden usar el breakinterior del cuerpo del ciclo "falso" anterior para lograr el mismo efecto.

Hormiga
fuente
7

Es una práctica muy común. En do . Trato de pensar en ello como si quisieras mentirte a ti mismo de una manera "No estoy usando un goto". Pensando en ello, no habría nada de malo con un gotouso similar. De hecho, también reduciría el nivel de sangría.

Sin embargo, dicho esto, noté, muy a menudo estos do..whilebucles tienden a crecer. Y luego obtienen ifsys elsedentro, lo que hace que el código en realidad no sea muy legible, y mucho menos comprobable.

Esos do..whilenormalmente están destinados a hacer una limpieza . Por todos los medios posibles, preferiría usar RAII y regresar temprano de una función corta . Por otro lado, C no le brinda tantas comodidades como lo hace C ++ , por lo que es do..whileuno de los mejores enfoques para hacer una limpieza.

Dmitry
fuente
6

Parece un programador en C. En C ++, las variables automáticas tienen destructores que se usan para limpiar, por lo que no debe haber nada necesario para ordenar antes del regreso. En C, no tenía este modismo RAII , por lo que si tiene un código de limpieza común, lo gotousa o usa un ciclo de paso único como se indicó anteriormente.

Su principal desventaja en comparación con el idioma de C ++ es que no se ordenará si se produce una excepción en el cuerpo. C no tenía excepciones, así que esto no fue un problema, pero sí lo convierte en un mal hábito en C ++.

Pete Kirkham
fuente
4

Varias explicaciones El primero es general, el segundo es específico para macros de preprocesador C con parámetros:

Control de flujo

He visto esto usado en código C simple. Básicamente, es una versión más segura de goto, ya que puede salir de ella y toda la memoria se limpia correctamente.

¿Por qué algo gotobueno sería bueno? Bueno, si usted tiene código donde prácticamente cada línea puede devolver un error, pero que necesita para reaccionar a todos ellos de la misma manera (por ejemplo, mediante la presentación del error al que llama después de limpiar), por lo general es más fácil de leer para evitar una if( error ) { /* cleanup and error string generation and return here */ }como evita la duplicación del código de limpieza.

Sin embargo, en C ++ tiene excepciones + RAII exactamente para este propósito, por lo que lo consideraría un mal estilo de codificación.

Comprobación de punto y coma

Si olvida el punto y coma después de una invocación de macro similar a una función, los argumentos pueden contraerse de forma no deseada y compilarse en una sintaxis válida. Imagina la macro

#define PRINT_IF_DEBUGMODE_ON(msg) if( gDebugModeOn ) printf("foo");

Eso se llama accidentalmente como

if( foo )
    PRINT_IF_DEBUGMODE_ON("Hullo\n")
else
    doSomethingElse();

El "más" se considerará asociado con el gDebugModeOn, por lo tanto, cuando foosea false, sucederá exactamente lo contrario de lo que se pretendía.

Proporcionando un alcance para variables temporales.

Dado que do / while tiene llaves, las variables temporales tienen un alcance claramente definido del que no pueden escapar.

Evitar advertencias de "punto y coma posiblemente no deseado"

Algunas macros solo se activan en versiones de depuración. Los define como:

#if DEBUG
#define DBG_PRINT_NUM(n) printf("%d\n",n);
#else
#define DBG_PRINT_NUM(n) 
#endif

Ahora, si usa esto en una versión de lanzamiento dentro de un condicional, se compila a

if( foo )
    ;

Muchos compiladores ven esto como lo mismo que

if( foo );

Que a menudo se escribe accidentalmente. Entonces recibes una advertencia. Do {} while (false) oculta esto del compilador y es aceptado por él como una indicación de que realmente no desea hacer nada aquí.

Evitar la captura de líneas por condicionales

Macro del ejemplo anterior:

if( foo )
    DBG_PRINT_NUM(42)
doSomething();

Ahora, en una compilación de depuración, ya que habitualmente también incluimos el punto y coma, esto se compila muy bien. Sin embargo, en la versión de lanzamiento, esto de repente se convierte en:

if( foo )

doSomething();

O más claramente formateado

if( foo )
    doSomething();

Lo cual no es en absoluto lo que se pretendía. Agregar un do {...} while (falso) alrededor de la macro convierte el punto y coma faltante en un error de compilación.

¿Qué significa eso para el OP?

En general, desea utilizar excepciones en C ++ para el manejo de errores y plantillas en lugar de macros. Sin embargo, en el caso muy raro en el que todavía necesita macros (por ejemplo, cuando genera nombres de clase usando pegado de token) o está restringido a C simple, este es un patrón útil.

uli testigo
fuente
Con respecto al alcance, no necesita el aparato de bucle; un bloque "sin adornos" es legal: x =1; y = 2; { int tmp = y; y = x; x = tmp; }.
chepner
Sin embargo, un bloque sin adornos no exige la presencia de un punto y coma faltante, lo que podría tener efectos secundarios no deseados. Do {} while (); REQUIERE el punto y coma y, por lo tanto, por ejemplo, no hace que las siguientes declaraciones se dibujen en un "si" si la macro no define nada en una versión de lanzamiento, como en mi ejemplo anterior.
uliwitness
¿No podría evitarse simplemente proporcionando una mejor definición para la macro? #define DBG_PRINT_NUM(n) {}.
chepner
1
No, porque {} es una declaración completa, es decir, equivalente a un ";". Entonces, si escribes if(a) DBG_PRINT_NUM(n); else other();, no se compilará. Solo if(a) {} else other();o if(a) ; else other();es válido, pero if(a) {}; else other();no lo es, porque eso hace que la cláusula "if" consista en dos declaraciones.
uliwitness
2

Tal vez se usa para que breakpueda usarse dentro para abortar la ejecución de código adicional en cualquier momento:

do {
    if (!condition1) break;
    some_code;
    if (!condition2) break;
    some_further_code;
    // …
} while(false);
Gumbo
fuente
77
Hacerlo parece un intento de evitar el uso gotosolo porque alguien escuchó que es "malo".
Anon
1
Quizás, pero C ++ tiene excepciones por esta misma razón.
TED
2

Creo que esto se hace para usar breako continuedeclaraciones. Algún tipo de lógica de código "goto".

Ivan Nevostruev
fuente
2

Es simple: aparentemente puedes salirte del bucle falso en cualquier momento usando la breakdeclaración. Además, el dobloque es un alcance separado (que también se podría lograr { ... }solo).

En tal situación, podría ser una mejor idea usar RAII (los objetos se destruyen automáticamente cuando finaliza la función). Otra construcción similar es el uso de goto: sí, sé que es malo , pero se puede usar para tener un código de limpieza común como este:

<return-type> function(<params>)
{
 <initialization>

 <main code for function using "goto error;" if something goes wrong>

 <tidy-up in success case & return>

 error:

 <commmon tidy-up actions for error case & return error code or throw exception>
}

(Como comentario aparte: la construcción do-while-false se usa en Lua para encontrar la continuedeclaración que falta ).

AndiDog
fuente
2

Muchos respondedores dieron la razón do{(...)break;}while(false). Me gustaría complementar la imagen con otro ejemplo más de la vida real.

En el siguiente código, tuve que establecer un enumerador operationbasado en la dirección apuntada por el datapuntero. Debido a que una caja de cambio solo se puede usar en tipos escalares primero, lo hice de manera ineficiente de esta manera

if (data == &array[o1])
    operation = O1;
else if (data == &array[o2])
    operation = O2;
else if (data == &array[on])
    operation = ON;

Log("operation:",operation);

Pero como Log () y el resto del código se repiten para cualquier valor de operación elegido, estaba divagando cómo omitir el resto de las comparaciones cuando la dirección ya se ha descubierto. Y aquí es dondedo{(...)break;}while(false) resulta útil.

do {
    if (data == &array[o1]) {
        operation = O1;
        break;
    }
    if (data == &array[o2]) {
        operation = O2;
        break;
    }
    if (data == &array[on]) {
        operation = ON;
        break;
    }
} while (false);

Log("operation:",operation);

Uno puede preguntarse por qué no podría hacer lo mismo breaken unif declaración, como:

if (data == &array[o1])
{
    operation = O1;
    break;
}
else if (...)

breakinteractúa únicamente con el cerramiento más cercano de bucle o un interruptor, ya sea una for, whileo do .. whiletipo, por lo que lamentablemente eso no va a funcionar.

4pie0
fuente
1

¿Cuántos años tenía el autor?

Pregunto porque una vez me encontré con un código Fortran en tiempo real que hizo eso, a fines de los años 80. Resulta que es una muy buena manera de simular hilos en un sistema operativo que no los tiene. Simplemente coloca todo el programa (su programador) en un bucle y llama a sus rutinas de "subproceso" una por una. Las rutinas de subprocesos en sí son bucles que se repiten hasta que ocurre una de una serie de condiciones (a menudo una es una cierta cantidad de ha pasado el tiempo). Es "multitarea cooperativa", ya que depende de los hilos individuales abandonar la CPU de vez en cuando para que los demás no se mueran de hambre. Puede anidar las llamadas de subprograma en bucle para simular la prioridad del hilo bandas.

TED
fuente
0

Estoy de acuerdo con la mayoría de los carteles sobre el uso como un goto apenas disfrazado. Las macros también se han mencionado como una motivación potencial para escribir código en el estilo.

También he visto esta construcción utilizada en entornos mixtos C / C ++ como la excepción de un hombre pobre. El "do {} while (false)" con un "break" se puede usar para saltar al final del bloque de código en caso de que se encuentre algo que normalmente garantizaría una excepción en el bucle.

También he enviado esta construcción utilizada en tiendas donde se aplica la ideología de "retorno único por función". Nuevamente, esto es en lugar de un "goto" explícito, pero la motivación es evitar múltiples puntos de retorno, no "omitir" el código y continuar la ejecución real dentro de esa función.

Stan Graves
fuente
0

Trabajo con Adobe InDesign SDK, y los ejemplos de InDesign SDK tienen casi todas las funciones escritas de esta manera. Es debido al hecho de que la función suele ser realmente larga. Donde necesita hacer QueryInterface (...) para obtener cualquier cosa del modelo de objetos de la aplicación. Por lo general, cada QueryInterface es seguido por ifno salió bien, descanso.

Kugel
fuente
0

Muchos ya han declarado la similitud entre este constructo y a goto, y expresaron una preferencia por el goto. ¿Quizás los antecedentes de esta persona incluían un entorno donde los goto estaban estrictamente prohibidos por las pautas de codificación?

Mark Ransom
fuente
0

La otra razón por la que se me ocurre es que decora los aparatos ortopédicos, mientras que creo que los aparatos desnudos estándar más nuevos de C ++ no están bien (a ISO C no le gustan). De lo contrario, para silenciar un analizador estático como pelusa.

No estoy seguro de por qué los querría, tal vez alcance variable o ventaja con un depurador.

Ver Trivial Do While loop , y las llaves son buenas de C2.

Para aclarar mi terminología (que creo que sigue el uso estándar):

Tirantes desnudos :

init();
...
{
c = NULL;
mkwidget(&c);
finishwidget(&c);
}
shutdown();

Tirantes vacíos (NOP):

{}

p.ej

while (1)
   {}  /* Do nothing, endless loop */

Bloque :

if (finished)
{
     closewindows(&windows);
     freememory(&cache);
}

que se convertiría

if (finished)
     closewindows(&windows);
freememory(&cache);

si se eliminan las llaves, alterando así el flujo de ejecución, no solo el alcance de las variables locales. Por lo tanto, no 'independiente' o 'desnudo'.

Se pueden usar llaves desnudas o un bloque para indicar cualquier sección de código que pueda ser una función (en línea) que desee marcar, pero no refactorizar en ese momento.

mctylr
fuente
De Verdad? Es una pena. Una de las pocas cosas que me gustó de C fue que te permitía declarar un nuevo alcance anidado en casi cualquier lugar.
TED
1
Los aparatos ortopédicos desnudos son ocasionalmente útiles para solucionar accidentes extraños. Ver blogs.msdn.com/oldnewthing/archive/2004/05/20/135841.aspx .
Brian
1
En C ++, un bloque (es decir, sus "llaves desnudas") se puede usar en cualquier lugar donde se permita una sola declaración.
Ben Voigt
@BenVoigt Las llaves vacías, es decir, un NOP es diferente de una "llave desnuda", que es un bloque agregado alrededor de una secuencia lineal de instrucciones. Por ejemplo, `printf (" Hola "); {putchar (','); putchar (0x20); } printf ("world! \ n"); `donde las llaves no son parte del control de bucle o rama.
mctylr
@mctylr: No estaba hablando de llaves vacías.
Ben Voigt
0

Es una forma artificial de emular a GOTOya que estos dos son prácticamente idénticos:

// NOTE: This is discouraged!
do {
    if (someCondition) break;
    // some code be here
} while (false);
// more code be here

y:

// NOTE: This is discouraged, too!
if (someCondition) goto marker;
// some code be here
marker:
// more code be here

Por otro lado, ambos realmente deberían hacerse con ifs:

if (!someCondition) {
    // some code be here
}
// more code be here

Aunque el anidamiento puede volverse un poco feo si solo convierte una larga cadena de reenvíos GOTOen anidados if. Sin embargo, la respuesta real es una refactorización adecuada, sin imitar construcciones de lenguaje arcaico.

Si intentabas desesperadamente transliterar un algoritmo con GOTOs, probablemente podrías hacerlo con este modismo. Sin embargo, no es estándar y es un buen indicador de que no te estás apegando a los modismos esperados del idioma.

No conozco ningún lenguaje tipo C donde do / while sea una solución idiomática para nada, en realidad.

Probablemente podría refactorizar todo el desastre en algo más sensato para hacerlo más idiomático y mucho más legible.

Alan ciruela
fuente
1
Alan, nodo..while(false) es para correr un número "indefinido" de veces, es para correr una vez .
Dmitry
2
Se está ejecutando un número indefinido de veces si tiene una continuedeclaración condicional al final como lo mostré. Por undefinedSimplemente significa que usted no sabe si se está ejecutando más de una vez, a menos que se puede predecir si las condiciones serán recibidos en una iteración específica. Sin ningún continues, do..while(false)se ejecutará una vez, pero también sin ningún breaks, while(true)se ejecutará para siempre, por lo que el "comportamiento predeterminado" no es realmente relevante para comprender qué se puede hacer con los bucles.
Alan Plum
Es útil cuando define una macro que tiene múltiples declaraciones. Si los envuelve en un do / while (falso), puede usar la macro en una instrucción if / else como cualquier otra llamada de función. ver noveltheory.com/TechPapers/while.htm para una explicación
John Paquin
55
Alguien no entiende la semántica de continue. continueNO repite el ciclo. "La continuedeclaración debe ocurrir solo en una declaración de iteración y hace que el control pase a la porción de continuación del ciclo de la declaración de iteración más pequeña , es decir, al final del ciclo".
Ben Voigt
-1, las dos primeras declaraciones no son idénticas por las razones que @BenVoigt señala.
cmh
0

Algunos codificadores prefieren tener una única salida / retorno de sus funciones. El uso de un dummy do {....} while (falso); le permite "salir" del bucle ficticio una vez que haya terminado y aún tenga un solo retorno.

Soy un programador de Java, así que mi ejemplo sería algo así como

import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class p45
{
    static List<String> cakeNames = Arrays.asList("schwarzwald torte", "princess", "icecream");
    static Set<Integer> forbidden = Stream.of(0, 2).collect(Collectors.toSet());

    public static  void main(String[] argv)
    {
        for (int i = 0; i < 4; i++)
        {
            System.out.println(String.format("cake(%d)=\"%s\"", i, describeCake(i)));
        }
    }


    static String describeCake(int typeOfCake)
    {
        String result = "unknown";
        do {
            // ensure type of cake is valid
            if (typeOfCake < 0 || typeOfCake >= cakeNames.size()) break;

            if (forbidden.contains(typeOfCake)) {
                result = "not for you!!";
                break;
            }

            result = cakeNames.get(typeOfCake);
        } while (false);
        return result;
    }
}
David Young
fuente
0

En tales casos yo uso

switch(true) {
   case condution1:
      ...
      break;
   case condution2:
      ...
      break;
}
Женя Остроушко
fuente
-1

Esto es divertido Probablemente hay interrupciones dentro del ciclo como otros han dicho. Lo hubiera hecho de esta manera:

while(true)
{
   <main code for function>
   break; // at the end.
}
fastcodejava
fuente
2
¿Con un potencial de bucle para siempre? do..while(false)siempre sale, while(true)es más arriesgado.
Dmitry
1
while(true)es el idioma correcto en la mayoría de los idiomas. A menudo lo encontrará en aplicaciones GUI como el bucle principal del programa. Debido a que básicamente está asumiendo que el programa no debería morir hasta que se le indique que lo haga, esto do..while(false)podría causar todo tipo de lógica artificial. Este enfoque puede ser más arriesgado desde un punto de vista perfeccionista, pero es semánticamente más fácil y, por lo tanto, menos propenso a errores para los programadores humanos (lo siento, Skynet).
Alan Plum
2
@dmitry do{...}while(false)es exactamente igual quewhile(true){ .. break;}
N 1.1
44
@ N1.1: No en presencia de continue, no son lo mismo.
Ben Voigt