Si hablamos en tiempo de compilación, incluso compiladores antiguos como el de Turbo C++ (para DOS) tenían la capacidad de detectar cosas como si había variables que nunca se usaban o código que nunca se iba a ejecutar (si estaba despúes de un
return y no había ningún
goto hacia este).
La dificultad de hacer eso depende de la complejidad del problema y es una tarea mejor realizada por un proceso automático porque requiere llevar el control de las variables que nunca se modificaron y también de las porciones de código que quedaron fuera del flujo normal de ejecución en todos los casos.
Si hablamos en tiempo de ejecución, tenemos que recordar que los compiladores modernos aplican optimizaciones, y el código generado casi nunca refleja el código fuente original.
Pero en términos generales, tenemos que tener una idea de cómo corre el código de máquina o bytecode en cuanto a las decisiones condicionales.
Para un IF, se aplican un grupo de reglas de precedencia de paréntesis, y cómo actuar ante combinaciones de AND y OR lógicos.
Por ejemplo, si tenemos 5 variables con AND:
if(variable1 && variable2 && variable3 && variable4 && variable5)
{
}
El programa tiene que asegurarse de que ambas variables/condiciones/expresiones se cumplan.
Si la primera, o segunda o tercera variable/condición/expresión no se cumple, entonces efectivamente llega hasta ahí y se salta comprobar el resto de expresiones. Un AND debe comprobar hasta el final, o saltarse el resto de la comprobación del IF sin ejecutar lo que contiene tan pronto como una condición no se cumpla.
Por ejemplo, si tenemos 5 variables con OR:
if(variable1 || variable2 || variable3 || variable4 || variable5)
{
}
En este caso, si la primera, o segunda variables se cumplen, entonces se salta el resto de la comprobación y ejecuta lo que contiene el IF.
Con OR, lo que contiene el IF se ejecuta tan pronto como se cumple una condición, ejecuta lo que contiene, y se salta el resto de las expresiones del IF.Con paréntesis y combinaciones de AND y OR esto se vuelve más complejo, pero es una cuestión de resolver paso a paso cada nivel de paréntesis en la secuencia correcta, y podemos ver para muchos casos qué partes de la expresión del IF se van a ejecutar y cuáles se van a saltar.
Los casos en los que todas las expresiones de un IF se cumplen son una minoría.También debemos recordar el comportamiento de las instrucciones, por ejemplo para procesadores x86, que sirven para saltos condicionales. Tenemos, entre otras, ja (mayor sin signo), jae (mayor o igual sin signo), jb (menor sin signo), jbe (menor o igual sin signo), je (igual), jne (no igual), además de usar jmp (salto incondicional) como útlimo recurso cuando todo el IF no se cumplió.
Para OR, es más eficiente usar el caso de la instrucción directamente reflejada por la expresión lógica, y para AND, es más eficiente usar la operación de salto condicional opuesta al de la expresión en el código fuente.