¿Cuántas veces se realiza la comparación [código] i> = n [/ código] en el siguiente programa? [código] int i = 200, n = 110; main () {while (i> = n) {i = i-1; n = n + 1;}} [/ código]

Editar: podría haber cometido un error al interpretar la salida del compilador de C escrita en [OLD Answer] Creo que leal -1(%rcx), %ecx está volcando basura en% ecx pero puede estar equivocado (en cuyo caso está ejecutando un ciclo regular con 47 comparaciones). Aquí hay una versión Java mejor y más fácil de entender.

[NUEVA respuesta]

La respuesta es 0. La respuesta también es 47.

La respuesta correcta es ¡Depende del compilador! Los compiladores modernos no son tan tontos como podría pensar. Pueden optimizar para el código que no hace nada. En este caso, suponiendo que se trata de un código Java, Proguard puede darse cuenta de que el ciclo while no hace nada y omite completamente la ejecución.

Aquí hay un código Java compilado por dos compiladores diferentes y sus códigos de bytes de salida.

Compilation1: compilador Java predeterminado

javac FunkyLoop.java

Produce un FunkyLoop.class que se parece a lo siguiente. Si observa, no se realizó ninguna optimización y simplemente empuja 200, 110 en la pila y ejecuta el código aumentando, decrementando y comparando de la manera que imaginó. Esta clase hará 47 comparaciones.

javap -c FunkyLoop.class
Compilado de “FunkyLoop.java”
clase pública FunkyLoop {
public FunkyLoop ();
Código:
0: aload_0
1: invokespecial # 1 // Método java / lang / Object. “” :() V
4: volver
public static void main (java.lang.String []);
Código:
0: sipush 200
3: istore_1
4: bipush 110
6: istore_2
7: iload_1
8: iload_2
9: if_icmplt 23
12: iload_1
13: iconst_1
14: isub
15: istore_1
16: iload_2
17: iconst_1
18: iadd
19: istore_2
20: ir a 7
23: regreso
}

Sin embargo, en la siguiente compilación, utilicé proguard, que es un analizador estático muy agresivo y elimina los bytecodes no utilizados para producir clases óptimas.

~ / Downloads / Softwares / DevelopmentTools / proguard6.0 / bin / proguard.sh -injars. -printmapping -dontwarn -keep ‘public class FunkyLoop {public static void main (java.lang.String []);}’ -outjars ./projar
javap -c projar / classes / classes / FunkyLoop.class
clase pública FunkyLoop {
public FunkyLoop ();
Código:
0: aload_0
1: invokespecial # 3 // Método java / lang / Object. “” :() V
4: volver
public static void main (java.lang.String []);
Código:
0: volver
}

¿Puedes ver lo que hizo? ¡No hay código dentro de la clase principal! Sabe que todo lo relacionado con el bucle no hace nada y simplemente lo arrojó. En este caso hay 0 comparaciones realizadas.

[ANTIGUA respuesta]

La respuesta es 1. La respuesta también es 47.

La respuesta correcta es ¡Depende del compilador! Los compiladores modernos no son tan tontos como podría pensar. Pueden optimizar para el código que no hace nada. En este caso, suponiendo que se trata de un código C, gcc puede descubrir que el bucle while no hace nada y omite completamente la ejecución.

para tu código

Mire el código de ensamblaje producido siguiendo el comando g ++

La imagen izquierda ( funky_loop_opt.s ) se produce activando el nivel de optimización g++ 3 ( -O3 ), mientras que la derecha ( funky_loop.s ) se produce por compilación predeterminada de g++ .

g ++ -S -O3 -o funky_loop_opt.s funky_loop.cpp
g ++ -S -o funky_loop.s funky_loop.cpp

Si observa de cerca, en funky_loop_opt.s , la línea 21 es donde solo se está haciendo una comparación entre %ecx, %eax (que se inicializan con 200 y 110 en la línea 16 y la línea 17 y son i, n respectivamente en su fuente C código). La magia real está sucediendo en la línea 22 donde está cargando el valor de basura (dirección de 1 byte debajo de la dirección de memoria %rcx ) en el registro %ecx (equivalente de i en el código C).

Por otro lado, en funky_loop.s , pasa por una disminución normal usando un registro de 64 bits y mucho más aritmética de 64 bits. Incremento, bucle de comparación. En este caso habrá un total de 46 comparaciones.

Primera comparación: i = 200, n = 110.

Fin de la primera iteración: i = 199, n = 111.

Cada iteración, i disminuye en 1 yn incrementos en 1. Por lo tanto, relativamente i yn se están acercando a una velocidad de 2 entre sí. Entonces

Al final de la 45ª iteración: i = 155, n = 155.

Como la comprobación es para i> = n, irá a la 46ª iteración y al final de la misma, i = 154, n = 156.

Hará una comparación más de (i> = n) (154> = 156) y fallará.

Entonces las comparaciones totales serán 46 + 1 = 47.

¿Desea una respuesta directa o la lógica detrás de esto? Puede resolverlo fácilmente. Verificará a menos que ambos sean iguales y en cada iteración su suma seguirá siendo la suma, para que pueda encontrar el punto de encuentro.

46 veces.

PD: compruébalo en Ideone.com