c++ - true - while n 1
¿Es "for(;;)" más rápido que "while(TRUE)"? Si no, ¿por qué la gente lo usa? (20)
for (;;) {
//Something to be done repeatedly
}
He visto mucho este tipo de cosas, pero creo que es bastante extraño ... ¿No sería mucho más claro decirlo while(true)
, o algo así?
Supongo que (como es la razón por la que muchos programadores recurren al código críptico), este es un pequeño margen más rápido.
¿Por qué y realmente vale la pena? Si es así, ¿por qué no simplemente definirlo de esta manera?
#define while(true) for(;;)
Ver también: ¿Qué es más rápido: mientras (1) o mientras (2)?
- No es más rápido.
- Si realmente te importa, compila con la salida del ensamblador para tu plataforma y mira para ver.
- No importa. Esto nunca importa. Escribe tus bucles infinitos como quieras.
¿Qué pasa si (si su idioma lo admite):
start:
/* BLAH */
goto start;
Ambos deberían ser iguales si su código está optimizado por el compilador. Para explicar lo que quiero decir con optimización, aquí hay un código de muestra escrito en MSVC 10:
int x = 0;
while(true) // for(;;)
{
x +=1;
printf("%d", x);
}
Si lo construye en modo Depuración ( sin ninguna optimización (/ Od) ) el desmontaje muestra la diferencia clara. Hay instrucciones adicionales para la true
condición dentro while
.
while(true)
00D313A5 mov eax,1 //extra
00D313AA test eax,eax //extra
00D313AC je main+39h (0D313B9h) //extra
{
x +=1;
00D313AE mov eax,dword ptr [x]
00D313B1 add eax,1
00D313B4 mov dword ptr [x],eax
printf("%d", x);
...
}
00D313B7 jmp main+25h (0D313A5h)
for(;;)
{
x +=1;
00D213A5 mov eax,dword ptr [x]
00D213A8 add eax,1
00D213AB mov dword ptr [x],eax
printf("%d", x);
...
}
00D213AE jmp main+25h (0D213A5h)
Sin embargo, si construye su código en modo Release (con Maximize Speed (/ O2) por defecto) obtendrá el mismo resultado para ambos. Ambos bucles se reducen a una instrucción de salto.
for(;;)
{
x +=1;
01291010 inc esi
printf("%d", x);
...
}
0129101C jmp main+10h (1291010h)
while(true)
{
x +=1;
00311010 inc esi
printf("%d", x);
...
}
0031101C jmp main+10h (311010h)
Lo que va a usar no importa para un compilador decente con la optimización de velocidad activada.
Ciertamente no es más rápido en ningún compilador sano. Ambos se compilarán en saltos incondicionales. La versión para es más fácil de escribir (como dijo Neil) y será clara si usted entiende la sintaxis de bucle.
Si tiene curiosidad, esto es lo que gcc 4.4.1 me da para x86. Ambos usan la instrucción x86 JMP .
void while_infinite()
{
while(1)
{
puts("while");
}
}
void for_infinite()
{
for(;;)
{
puts("for");
}
}
compila para (en parte):
.LC0:
.string "while"
.text
.globl while_infinite
.type while_infinite, @function
while_infinite:
pushl %ebp
movl %esp, %ebp
subl $24, %esp
.L2:
movl $.LC0, (%esp)
call puts
jmp .L2
.size while_infinite, .-while_infinite
.section .rodata
.LC1:
.string "for"
.text
.globl for_infinite
.type for_infinite, @function
for_infinite:
pushl %ebp
movl %esp, %ebp
subl $24, %esp
.L5:
movl $.LC1, (%esp)
call puts
jmp .L5
.size for_infinite, .-for_infinite
El ciclo "para siempre" es popular en los sistemas integrados como un bucle de fondo. Algunas personas lo implementan como:
for (; ;)
{
// Stuff done in background loop
}
Y a veces se implementa como:
while (TRUE /* or use 1 */)
{
// Stuff done in background loop
}
Y otra implementación más es:
do
{
// Stuff done in background loop
} while (1 /* or TRUE */);
Un compilador de optimización debe generar el mismo o similar código de ensamblaje para estos fragmentos. Una nota importante: el tiempo de ejecución de los bucles no es una gran preocupación, ya que estos bucles continúan para siempre, y se gasta más tiempo en la sección de procesamiento.
Es una cuestión de preferencia personal que camino es más rápido. Personalmente, soy una persona sensible al tacto y nunca miro mi teclado, durante la programación, puedo tocar todas las 104 teclas de mi teclado.
Me parece más rápido escribir "while (TRUE)".
Mentalmente agregué algunas mediciones del movimiento de los dedos y las totalicé. "for (;;)" tiene aproximadamente 12 anchos de tecla de retroceso y cuarto (entre las teclas de inicio y las teclas, y entre las teclas de inicio y la tecla MAYÚS) "while (TRUE)" tiene alrededor de 14 anchos de teclas de movimientos hacia atrás y cuarto.
Sin embargo, soy mucho menos propenso a errores cuando escribo este último. Mentalmente pienso en palabras a la vez, así que me resulta más rápido escribir cosas como "nIndex" que acrónimos como "nIdx" porque realmente tengo que deletrear mentalmente las letras en lugar de hablarlas dentro de mi mente y dejar que mis dedos sean automáticos. tipo de la palabra (como andar en bicicleta)
(Mi punto de referencia de TypingTest.com = 136 palabras por minuto)
He visto que algunas personas lo prefieren porque tienen un #define en algún lugar como este:
#define EVER ;;
Lo que les permite escribir esto:
for (EVER)
{
/* blah */
}
La razón más importante para usar "for (;;)" es el miedo de usar "while (TRUE)" cuando realiza una programación exploratoria. Es más fácil controlar la cantidad de repeticiones con "para", y también, es más fácil convertir el bucle "para" en infinito.
Por ejemplo, si está construyendo una función recursiva, puede limitar la cantidad de llamadas a la función antes de convertirla en un ciclo infinito.
for(int i=0;i<1000;i++) recursiveFunction(oneParam);
Cuando estoy seguro de mi función, la convierto en un ciclo infinito:
for(;;) recursiveFunction(oneParam);
No hay diferencia en términos del código máquina que se genera.
Sin embargo, solo para rebelar la tendencia, yo diría que la forma while (TRUE) es mucho más legible e intuitiva que para (;;), y que la legibilidad y claridad son razones mucho más importantes para las pautas de codificación que cualquier otra razón. he escuchado para el enfoque de (;;) (prefiero basar mis pautas de codificación en un razonamiento sólido y / o en una prueba de efectividad).
No puedo imaginar que un compilador valioso genere cualquier código diferente. Incluso si lo hiciera, no habría forma de determinar sin probar el compilador particular que era más eficiente.
Sin embargo, sugiero que prefiera for(;;)
por los siguientes motivos:
un número de compiladores que he usado generará una advertencia de expresión constante para while (verdadero) con las configuraciones de nivel de advertencia apropiadas.
en su ejemplo, la macro VERDADERO no se puede definir como espera
hay muchas variantes posibles del ciclo while infinito, como
while(1)
,while(true)
,while(1==1)
etc .; entoncesfor(;;)
es probable que resulte en una mayor coherencia.
No solo un patrón conocido, sino una expresión estándar en C (y C ++)
Personalmente prefiero la expresión for (;;)
(que se compilará con el mismo código que while (TRUE)
.
El uso de while (TRUE)
puede ser más legible en un sentido, he decidido usar el for (;;)
porque se destaca .
Una construcción infinita de bucles debería notarse fácilmente o llamarse en código, y personalmente creo que el estilo for (;;)
hace esto un poco mejor que while (TRUE)
o while (1)
.
Además, recuerdo que algunos compiladores emiten advertencias cuando la expresión de control de un ciclo while es una constante. No creo que eso pase demasiado, pero el potencial de advertencias falsas es suficiente para que yo quiera evitarlo.
Personalmente uso for (;;)
porque no hay ningún número en él, es solo una palabra clave. Lo prefiero a while (true)
, while (1)
, while (42)
, while (!0)
etc etc.
Supongo que while (true) es más legible que para (;;) - parece que el programador pierde algo en el ciclo :)
y a quién le importa cuál es más rápido si hay alguno
Todas las buenas respuestas: el comportamiento debe ser exactamente el mismo.
SIN EMBARGO, supongo que HIZO una diferencia. Supongamos que uno de ellos tomó 3 instrucciones más por iteración.
¿Deberías importarte?
SOLO si lo que haces dentro del ciclo es casi nada , lo cual casi nunca es el caso.
Mi punto es que hay micro-optimización y macro-optimización. La micro-optimización es como "cortarse el pelo para perder peso".
Yo prefiero for (;;)
porque es el más consistente en diferentes lenguajes tipo C.
En C ++ while (true)
está bien, pero en C dependes de un encabezado para definir true
, aunque TRUE
es una macro de uso común. Si usa while (1)
es correcto en C, C ++ y JavaScript, pero no en Java o C #, que requieren que la condición de bucle sea booleana, como while (true)
o while (1 == 1)
. En PHP, las palabras clave no distinguen entre mayúsculas y minúsculas, pero el idioma prefiere el uso de mayúsculas TRUE
.
Sin embargo, for (;;)
siempre es completamente correcto en todos esos idiomas.
Yo prefiero for(;;)
por dos razones.
Una es que algunos compiladores producen advertencias en while(true)
(algo así como "la condición de bucle es constante"). Siempre es bueno evitar advertencias.
Otra es que creo for(;;)
es más clara y más reveladora. Quiero un ciclo infinito. Literalmente no tiene ninguna condición, no depende de nada. Solo quiero que continúe para siempre, hasta que haga algo para salir de eso.
Mientras que con while(true)
, bueno, ¿qué tiene de cierto que ver con algo? No estoy interesado en el bucle hasta que true se convierte en falso, que es lo que esta forma dice literalmente (loop while true es verdadero). Solo quiero repetir.
Y no, no hay absolutamente ninguna diferencia de rendimiento.
Por Dennis Ritchie
Empecé a usar
for (;;)
porque así es como lo hace Dennis Ritchie en K & R, y cuando estoy aprendiendo un nuevo idioma siempre trato de imitar a los chicos inteligentes.Esto es idiomático C / C ++. Probablemente sea mejor a la larga acostumbrarse si planea hacer mucho en el espacio C / C ++.
Su
#define
no funcionará, ya que lo # que está siendo # defined''d tiene que parecerse a un identificador de C.Todos los compiladores modernos generarán el mismo código para las dos construcciones.
for(;;Sleep(50))
{
// Lots of code
}
Es más claro que:
while(true)
{
// Lots of code
Sleep(50);
}
No es que esto se aplique si no está utilizando Sleep()
.
while(true)
genera una advertencia con Visual Studio (la condición es constante). La mayoría de los lugares en los que he trabajado compilan compilaciones de producción con advertencias como errores. Asi que
for(;;)
se prefiere.