¿Para vs. mientras estás en programación C?


78

Hay tres bucles en C: for, whileydo-while . ¿Cual es la diferencia entre ellos?

Por ejemplo, parece que casi todas las whiledeclaraciones se pueden reemplazar por fordeclaraciones, ¿verdad? Entonces, ¿cuál es la ventaja de usar while?


9
Olvidaste el GOTObucle condicional . Si bien la gente no lo considera un bucle, creo que todos los bucles esencialmente se compilan en bucles GOTO condicionales.
Armstrongest

1
¿No se considera la recursividad también como bucle?
Nyan

¿No sería más fácil escribir un compilador que en x86 compile un bucle for simple en la loopinstrucción más eficiente (resta, comparación y salto en una sola instrucción), que uno que compile whileen la loopinstrucción? ¿Los compiladores actuales compilan foren una loopinstrucción?
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

Respuestas:


166

Un ciclo while siempre evaluará la condición primero.

Un bucle do / while siempre ejecutará el código en el do{}bloque primero y luego evaluará la condición.

Un bucle for le permite iniciar una variable de contador, una condición de verificación y una forma de incrementar su contador, todo en una línea.

Al final del día, todos siguen siendo bucles, pero ofrecen cierta flexibilidad en cuanto a cómo se ejecutan.

Aquí hay una gran explicación del razonamiento detrás del uso de cada tipo diferente de bucle que puede ayudar a aclarar las cosas. Gracias clyfe

La principal diferencia entre las for'sy las while' es una cuestión de pragmática: usualmente usamos forcuando hay un número conocido de iteraciones, y usamos whileconstrucciones cuando el número de iteraciones no se conoce de antemano. El problema de whilevs do ... whiletambién es pragmático, el segundo ejecuta las instrucciones una vez al inicio y luego se comporta como el simple while.


Los bucles for son especialmente agradables porque son concisos. Para ello, el bucle for:

para ser escrito como un bucle while, tendría que hacer lo siguiente:

En este caso, hay más cosas que seguir y count++;podrían perderse en la lógica. Esto podría terminar siendo problemático dependiendo de dónde countse incremente y si debe incrementarse o no antes o después de la lógica del ciclo. Con un forciclo, su variable de contador siempre se incrementa antes de la siguiente iteración del ciclo, lo que agrega cierta uniformidad a su código.


En aras de la integridad, probablemente sea significativo hablar breakycontinue declaraciones aquí, que vienen muy bien cuando se hace el procesamiento de bucle.

break terminará instantáneamente el ciclo actual y no se ejecutarán más iteraciones.

continue terminará la iteración actual y pasará a la siguiente.

Tenga en cuenta que en un bucle for, continueevalúa la part3expresión de for (part1; part2; part3); en contraste, en un ciclo while, simplemente salta para reevaluar la condición del ciclo.


7
¿Debería discutir el comportamiento de 'continuar'; en un bucle 'for' vs un bucle 'while'? De lo contrario, buena respuesta.
Jonathan Leffler

3
+1 para una excelente respuesta. Vale la pena señalar: los bucles for no requieren una variable de contador. En los lenguajes de estilo C, en realidad son para (<instrucción de inicio>; <continuación>; <ejecutar después de cada iteración>). Da la casualidad de que el uso más común es la variable de contador: for (int x = 0 [start]; x <100 [continue?]; ++ x [post-iteration])
Sean Edwards

10
La principal diferencia entre el for'sy el while'ses una cuestión de pragmática: usualmente usamos forcuando hay un número conocido de iteraciones , y usamos whileconstrucciones cuando el número de iteraciones no se conoce de antemano . El problema de whilevs do ... whiletambién es pragmático, el segundo ejecuta las instrucciones una vez al inicio, y luego se comporta como el simple while.
Clyfe

2
+1 respuesta bien escrita y, a veces, revisar los "conceptos básicos" es bueno para todos
JYelton

1
Me encanta la respuesta, es decir, la parte en la que se habla de uniformidad en el aumento del contador en caso de un 'para' versus potencialmente en cualquier parte de la iteración en caso de un 'mientras'. Para ser honesto, nunca lo hubiera dicho de manera tan elocuente, aunque no hay muchas novedades aquí
Shravan

16

Si existe una gran preocupación por la velocidad y el rendimiento, el mejor enfoque es verificar el código producido por el compilador a nivel de ensamblado.

Por ejemplo, el siguiente código muestra que "do-while" es un poco más rápido. Esto se debe a que el ciclo "do-while" no usa la instrucción "jmp".

Por cierto, en este ejemplo específico, el peor de los casos lo da el bucle "for". :))

// "EN BUCLE:

// BUCLE "MIENTRAS":

// BUCLE "HACER MIENTRAS":


11

Por el bien de la legibilidad


3
Para el caso, también puede usar goto como un bucle.
WhirlWind

Por otro lado, hay recursividad. Y puede reemplazar cualquier estilo de bucle con cualquier otro estilo.
WhirlWind

10
De hecho ... todos los bucles son en realidad ramas GOTO de lujo.
Armstrongest

@WhirlWind Excepto que en lenguajes sin recursividad probablemente terminará con desbordamientos de pila. (Y podría terminar aquí preguntando sobre los desbordamientos de pila, lo que me haría sonreír un poco).
Sean Edwards

@Sean sí, estaba pensando en eso, y si hay una manera de evitar el desbordamiento de la pila. Por supuesto, si hay recursividad de cola ...
WhirlWind

10

Todos son intercambiables; podría elegir un tipo y no usar nada más que eso para siempre, pero generalmente uno es más conveniente para una tarea determinada. Es como decir "¿por qué cambiar? Puedes usar un montón de declaraciones if"; es cierto, pero si es un patrón común para verificar una variable para un conjunto de valores, es conveniente y mucho más fácil de leer si hay una característica de idioma. Para hacer eso


4
Realmente no. Tanto for como while pueden ejecutar el cuerpo cero veces; un do while no puede.

4
@Neil do {if(!cond) break; /* do stuff */ } while(cond);. Feo y repetitivo, pero ese es mi punto sobre por qué existen variaciones :)
Michael Mrozek

@Neil: puede usar una bandera adicional para omitir la primera ejecución. Interchangeable no dice nada sobre lo fácil o útil que es. ;)
Asegure el

3
El cuerpo del bucle todavía se ingresa; este no es el caso de while y for.

2
@Neil Bueno, para ciertas definiciones de "cuerpo del bucle". Causa el mismo comportamiento de cualquier manera - no ejecuta la /* do stuff */pieza si condes falsa
Michael Mrozek

8

Si desea que un bucle se ejecute mientras una condición es verdadera, y no para un cierto número de iteraciones, es mucho más fácil de entender para otra persona:

que algo como esto:


No sé mucho más fácil. Me arriesgaría a adivinar que si C no tuviera la primera forma, todos estaríamos bastante acostumbrados a ver la segunda a estas alturas.
caf

Es bastante justo, pero te garantizo que estaría pensando "WTF" si viera la segunda versión en cualquier código que mantuviera ...
Justin Ethier

2
El código debe leerse en prosa, el primero está mucho más cerca del lenguaje natural. Quizás no sea "mucho más fácil", pero probablemente mucho más rápido de reconocer y comprender.
FredCooke

5

Recuerde, un forbucle es esencialmente un whilebucle elegante . Son lo mismo.

La ventaja de un bucle for es que es más difícil hacer accidentalmente un bucle infinito. O más bien, es más obvio cuando haces uno porque generalmente pones el bucle var en la declaración inicial.

Un whilebucle es más claro cuando no está haciendo un patrón de incremento estándar. Por ejemplo:


6
Sin embargo, hay una diferencia sutil entre for () y escribirlo como un while (): cambia el comportamiento de continue. Para el caso for (), continue ejecuta el paso de incremento antes de verificar la condición, mientras que en el caso while () continue saltará directamente a la condición.
Rup

Sí, muy buen punto. Además, creo que lo que la gente olvida es que cuando llega, todos los bucles se compilan en declaraciones GOTO.
Armstrongest

Creo que esta es la razón por la que los bucles while conducen más a menudo a errores de bucle infinito: el paso de incremento se puede omitir con un continue en algún lugar.
Michael Mathews

@Michael: Sí, muy cierto. forLos bucles probablemente se introdujeron como métodos convenientes y productivos.
Armstrongest

@Rup Un muy buen punto. Siempre lo he considerado azúcar sintáctico por un tiempo, pero el comportamiento continuo significa que no es cierto.
JeremyP

4

Debería utilizar un bucle de este tipo que se adapte más a sus necesidades. Por ejemplo:

Obviamente, en tal situación, "para" se ve mejor que "mientras". Y "hacer mientras" debe usarse cuando algunas operaciones deben realizarse antes del momento en que se verificará la condición de su ciclo.

Perdón por mi mal ingles).


4

Un malentendido común con while/ forloops que he visto es que su eficiencia es diferente. Whilelos bucles y los forbucles son igualmente eficientes . Recuerdo que mi profesor de informática de la escuela secundaria me dijo que los bucles for son más eficientes para la iteración cuando tienes que incrementar un número. Ese no es el caso.

Forlos bucles son simplemente azucarados sintácticamente while y hacen que el código de iteración sea más rápido de escribir.

Cuando el compilador toma su código y lo compila, lo está traduciendo a una forma que es más fácil de entender y ejecutar para la computadora en un nivel inferior (ensamblado). Durante esta traducción, las diferencias sutiles entre las sintaxis whiley forse pierden y se vuelven exactamente iguales.


"Los bucles for son simplemente azucarados sintácticamente mientras que los bucles": como ya se ha señalado en uno de los comentarios anteriores, esto no es estrictamente correcto. Un continue dentro de un for no omite la expresión de bucle (por ejemplo, el i ++ in for (i = 0 i < limit ; i++).
JeremyP

3

UN for sugiera una iteración fija usando un índice o variantes en este esquema.

A whileydo... while son construcciones que utiliza cuando existe una condición que debe comprobarse cada vez (aparte de algunas construcciones similares a índices, consulte más arriba). Se diferencian en cuándo se realiza la primera ejecución de la verificación de condición.

Puede usar cualquier construcción, pero tienen sus ventajas y desventajas según su caso de uso.


3

Hace algún tiempo, noté que un bucle For generalmente genera varias instrucciones de máquina más que un bucle while. Sin embargo, si observa detenidamente los ejemplos, que reflejan mis observaciones, la diferencia son dos o tres instrucciones de máquina, que apenas merecen mucha consideración.

Tenga en cuenta también que el inicializador de un bucle WHILE puede eliminarse introduciéndolo en el código, por ejemplo:

El modificador estático cuece el valor inicial en el código, ahorrando (redoble de batería) una instrucción MOV. Más importante aún, marcar una variable como estática la mueve fuera del marco de la pila. Si la alineación variable lo permite, también puede producir un código ligeramente más pequeño, ya que la instrucción MOV y sus operandos ocupan más espacio que, por ejemplo, un valor entero, booleano o de carácter (ya sea ANSI o Unicode).

Sin embargo, si las variables están alineadas en límites de 8 bytes, una configuración predeterminada común, un int, bool o TCHAR integrado en el código cuesta el mismo número de bytes que una instrucción MOV.


2

Todos son iguales en el trabajo que realizan. Puedes hacer las mismas cosas usando cualquiera de ellos. Pero difieren en cuanto a legibilidad, usabilidad, conveniencia, etc.


2

Una diferencia entre while y do-while es que while comprueba la condición del bucle y, si es cierto, se ejecuta el cuerpo y se vuelve a comprobar la condición. Do-while comprueba la condición después de la ejecución del cuerpo, por lo que con do-while el cuerpo se ejecuta al menos una vez.

Por supuesto, puede escribir un bucle while como do-while y vv, pero esto generalmente requiere cierta duplicación de código.


2

Una peculiaridad del do whilees que necesita un punto y coma después de un tiempo para completar. A menudo se utiliza en las definiciones de macros para ejecutar varias sentencias solo una vez mientras se restringe el impacto de la macro. Si las macros se definieron como bloques, pueden producirse algunos errores de análisis.

Una explicación entre otras


1
Sin embargo, eso es terriblemente hackeo, esa no es una gran razón para que do-whileexista
Michael Mrozek

nop, yo nunca dije eso, pero ese es un uso realmente particular para hacer mientras, que es bastante generalizado.
LB40

@Michael, sí, es un truco, pero es uno de uso muy común que hace que una macro que contenga varias declaraciones se comporte completamente como se espera en todos los contextos sintácticos.
JeremyP

@JeremyP Lo sé, también lo uso, pero no es un caso de uso real do-while, solo se usa porque crea un bloque y aún requiere un punto y coma al final
Michael Mrozek

Solo quería señalar este uso particular de do-while. Parte de la pregunta era, cuáles son las diferencias ... y esa es una diferencia. (pero estoy de acuerdo, eso es hackish)
LB40

2

Los bucles for (al menos considerando C99) son superiores a los bucles while porque limitan el alcance de la (s) variable (s) incrementada (s).

Los bucles Do while son útiles cuando la condición depende de algunas entradas. Son los que menos se utilizan de los tres tipos de bucle.


2

Entre for y while: while no necesita inicialización ni declaración de actualización, por lo que puede verse mejor, más elegante; forpuede tener declaraciones faltantes, una, dos o todas, por lo que es la más flexible y obvia si necesita inicialización, condición de bucle y "actualización" antes de bucle. Si solo necesita la condición del bucle (probado al comienzo del bucle), entonces whilees más elegante.

Entre for / while y do-while : en do-whilela condición se evalúa al final del ciclo. Más cómodo si el bucle debe ejecutarse al menos una vez.


2

MIENTRAS es más flexible. FOR es más conciso en aquellos casos en los que se aplica.

FOR es ideal para bucles que tienen algún tipo de contador, como

Puede lograr lo mismo con un WHILE, por supuesto, como otros han señalado, pero ahora la inicialización, la prueba y el incremento se dividen en tres líneas. Posiblemente tres líneas muy separadas si el cuerpo del bucle es grande. Esto dificulta que el lector vea lo que estás haciendo. Después de todo, aunque "++ n" es una tercera pieza muy común de FOR, ciertamente no es la única posibilidad. He escrito muchos bucles donde escribo "n + = incremento" o alguna expresión más compleja.

Por supuesto, FOR también puede funcionar bien con otras cosas que no sean un mostrador. Me gusta

Etc.

Pero FOR se rompe cuando la lógica de "la próxima vez que pasa por el bucle" se vuelve más complicada. Considerar:

Es decir, si el proceso de avance puede ser diferente dependiendo de las condiciones encontradas durante el procesamiento, una instrucción FOR no es práctica. Sí, a veces se puede hacer que funcione con expresiones bastante complicadas, uso del operador ternario?:, Etc., pero eso normalmente hace que el código sea menos legible en lugar de más legible.

En la práctica, la mayoría de mis bucles pasan por una matriz o estructura de algún tipo, en cuyo caso utilizo un bucle FOR; o están leyendo un archivo o un conjunto de resultados de una base de datos, en cuyo caso uso un bucle WHILE ("while (! eof ())" o algo por el estilo).


Si el encabezado for se vuelve demasiado largo, simplemente divida la línea después de un punto y coma. Este no es un argumento a favor de while en lugar de a favor.
klutt

@klutt El problema con una expresión larga y complicada que involucra operadores ternarios anidados y seis niveles de paréntesis o alguna complejidad comparable no es per se que la línea sea demasiado larga para caber en la ventana del editor, sino que se vuelve difícil de leer y comprender.
Jay

Es cierto, pero eso no tiene nada que ver con el tipo de bucle que elijas.
klutt

@klutt Claro que sí. Si la operación "siguiente" implica una lógica compleja con muchas condiciones, no se puede colocar fácilmente en un bucle FOR. Tendría que tener una expresión compleja con ternaries anidados o algo así, o tendría que tomar la siguiente de la declaración FOR y ponerla en el cuerpo del bucle. En ese momento, también puede escribir un bucle WHILE.
Jay

2

Son prácticamente iguales excepto por el do-whilebucle. El forbucle es bueno cuando tienes un countertipo de variable. Lo hace obvio. whileEl bucle tiene sentido en los casos en que se comprueba una bandera como se muestra a continuación:



0

/ * bucle while

5 dólares

1 chocolate = 1 dólar

Vengo a casa y no puedo ir a comprar porque mi dinero = 0 dólares * /

Dinero infinito

visite este video para comprender mejor https://www.youtube.com/watch?v=eqDv2wxDMJ8&t=25s

/* en bucle

5 dólares

* /

Para una mejor comprensión, visite https://www.youtube.com/watch?v=_vdvyzzp-R4&t=25s

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.