Pregunta de la entrevista: ¿Cuál se ejecutará más rápido if (flag==0)o if (0==flag)? ¿Por qué?
if(flag = 0)al precio de un poco de legibilidad.
Pregunta de la entrevista: ¿Cuál se ejecutará más rápido if (flag==0)o if (0==flag)? ¿Por qué?
if(flag = 0)al precio de un poco de legibilidad.
Respuestas:
Todavía no he visto ninguna respuesta correcta (y ya hay algunas) advertencia: Nawaz señaló la trampa definida por el usuario . Y lamento mi voto a favor apresurado sobre la "pregunta más estúpida" porque parece que muchos no lo hicieron bien y da lugar a una buena discusión sobre la optimización del compilador :)
La respuesta es:
¿Qué es
flagel tipo?
En el caso de que en flagrealidad sea un tipo definido por el usuario. Entonces depende de qué sobrecarga deoperator== se seleccione. Por supuesto que puede parecer estúpido que no sean simétricos, pero ciertamente está permitido, y ya he visto otros abusos.
Si flag es incorporado, ambos deben tener la misma velocidad.
Del artículo de Wikipedia sobre x86, apostaría por una Jxxinstrucción para la ifdeclaración: tal vez un JNZ(Jump if Not Zero) o algo equivalente.
Dudo que el compilador pierda una optimización tan obvia, incluso con las optimizaciones desactivadas. Este es el tipo de cosas para las que está diseñada la optimización de mirilla .
EDITAR: Surgió de nuevo, así que agreguemos un poco de ensamblaje (LLVM 2.7 IR)
int regular(int c) {
if (c == 0) { return 0; }
return 1;
}
int yoda(int c) {
if (0 == c) { return 0; }
return 1;
}
define i32 @regular(i32 %c) nounwind readnone {
entry:
%not. = icmp ne i32 %c, 0 ; <i1> [#uses=1]
%.0 = zext i1 %not. to i32 ; <i32> [#uses=1]
ret i32 %.0
}
define i32 @yoda(i32 %c) nounwind readnone {
entry:
%not. = icmp ne i32 %c, 0 ; <i1> [#uses=1]
%.0 = zext i1 %not. to i32 ; <i32> [#uses=1]
ret i32 %.0
}
Incluso si uno no sabe cómo leer el IR, creo que se explica por sí mismo.
flagdebe ser un número entero o booleano. OTOH, tener una variable nombrada flagde un tipo definido por el usuario es bastante incorrecto en sí mismo, en mi humilde opinión
#includedirectiva. Por razones de simplicidad, por lo general asciende a int, char, booly similares. Todos los demás tipos se dice que son definidos por el usuario, es decir que existen, ya que son el resultado de algún usuario declarándolos: typedef, enum, struct, class. Por ejemplo, std::stringestá definido por el usuario, aunque ciertamente no lo definió usted mismo :)
Mismo código para amd64 con GCC 4.1.2:
.loc 1 4 0 # int f = argc;
movl -20(%rbp), %eax
movl %eax, -4(%rbp)
.loc 1 6 0 # if( f == 0 ) {
cmpl $0, -4(%rbp)
jne .L2
.loc 1 7 0 # return 0;
movl $0, -36(%rbp)
jmp .L4
.loc 1 8 0 # }
.L2:
.loc 1 10 0 # if( 0 == f ) {
cmpl $0, -4(%rbp)
jne .L5
.loc 1 11 0 # return 1;
movl $1, -36(%rbp)
jmp .L4
.loc 1 12 0 # }
.L5:
.loc 1 14 0 # return 2;
movl $2, -36(%rbp)
.L4:
movl -36(%rbp), %eax
.loc 1 15 0 # }
leave
ret
No habrá diferencia en sus versiones.
Supongo que la typebandera of no es un tipo definido por el usuario, sino que es un tipo integrado. ¡Enum es una excepción!. Puede tratar enum como si estuviera integrado. De hecho, ¡los valores de it son uno de los tipos integrados!
En caso de que sea un tipo definido por el usuario (excepto enum), entonces la respuesta depende completamente de cómo haya sobrecargado al operador ==. Tenga en cuenta que debe sobrecargar ==al definir dos funciones, ¡una para cada una de sus versiones!
No hay absolutamente ninguna diferencia.
Sin embargo, puede ganar puntos al responder la pregunta de la entrevista al referirse a la eliminación de errores tipográficos de asignación / comparación:
if (flag = 0) // typo here
{
// code never executes
}
if (0 = flag) // typo and syntactic error -> compiler complains
{
// ...
}
Si bien es cierto que, por ejemplo, un compilador C advierte en el caso del primero ( flag = 0), no existen tales advertencias en PHP, Perl o Javascript o <insert language here>.
No habrá absolutamente ninguna diferencia en cuanto a velocidad. ¿Por qué debería haberlo?
x == 0podría usarla pero 0 == xpodría usar una comparación normal. Dije que tendría que retrasarse.
virtual operator==(int)un tipo definido por el usuario?
Bueno, hay una diferencia cuando la bandera es un tipo definido por el usuario
struct sInt
{
sInt( int i ) : wrappedInt(i)
{
std::cout << "ctor called" << std::endl;
}
operator int()
{
std::cout << "operator int()" << std::endl;
return wrappedInt;
}
bool operator==(int nComp)
{
std::cout << "bool operator==(int nComp)" << std::endl;
return (nComp == wrappedInt);
}
int wrappedInt;
};
int
_tmain(int argc, _TCHAR* argv[])
{
sInt s(0);
//in this case this will probably be faster
if ( 0 == s )
{
std::cout << "equal" << std::endl;
}
if ( s == 0 )
{
std::cout << "equal" << std::endl;
}
}
En el primer caso (0 == s) se llama al operador de conversión y luego el resultado devuelto se compara con 0. En el segundo caso se llama al operador ==.
En caso de duda, evalúelo y aprenda la verdad.
Deberían ser exactamente iguales en términos de velocidad.
Sin embargo, observe que algunas personas suelen poner la constante a la izquierda en comparaciones de igualdad (los llamados "condicionales de Yoda") para evitar todos los errores que pueden surgir si escribe =(operador de asignación) en lugar de ==(operador de comparación de igualdad); dado que la asignación a un literal desencadena un error de compilación, se evita este tipo de error.
if(flag=0) // <--- typo: = instead of ==; flag is now set to 0
{
// this is never executed
}
if(0=flag) // <--- compiler error, cannot assign value to literal
{
}
Por otro lado, la mayoría de la gente encuentra los "condicionales de Yoda" raros y molestos, especialmente porque la clase de errores que previenen se pueden detectar también mediante el uso de advertencias adecuadas del compilador.
if(flag=0) // <--- warning: assignment in conditional expression
{
}
Como han dicho otros, no hay diferencia.
0 tiene que ser evaluado. flagtiene que ser evaluado. Este proceso lleva el mismo tiempo, sin importar de qué lado se coloquen.
La respuesta correcta sería: ambos tienen la misma velocidad.
¡Incluso las expresiones if(flag==0)y if(0==flag)tienen la misma cantidad de caracteres! Si uno de ellos estuviera escrito comoif(flag== 0) , entonces el compilador tendría un espacio adicional para analizar, por lo que tendría una razón legítima para señalar el tiempo de compilación.
Pero como no existe tal cosa, no hay absolutamente ninguna razón por la que uno deba ser más rápido que otro. Si hay una razón, entonces el compilador está haciendo cosas muy, muy extrañas con el código generado ...
Cuál es rápido depende de la versión de == que estés usando. Aquí hay un fragmento que usa 2 posibles implementaciones de ==, y dependiendo de si elige llamar a x == 0 o 0 == x, se selecciona una de las 2.
Si solo está usando un POD, esto realmente no debería importar cuando se trata de velocidad.
#include <iostream>
using namespace std;
class x {
public:
bool operator==(int x) { cout << "hello\n"; return 0; }
friend bool operator==(int x, const x& a) { cout << "world\n"; return 0; }
};
int main()
{
x x1;
//int m = 0;
int k = (x1 == 0);
int j = (0 == x1);
}
Bueno, estoy completamente de acuerdo con todo lo dicho en los comentarios al OP, por el bien del ejercicio:
Si el compilador no es lo suficientemente inteligente (de hecho, no debería usarlo) o la optimización está deshabilitada, x == 0podría compilar en una jump if zeroinstrucción de ensamblaje nativa , mientras0 == x podría ser una comparación más genérica (y costosa) de valores numéricos.
Aún así, no me gustaría trabajar para un jefe que piensa en estos términos ...
Seguramente no hay diferencia en cuanto a velocidades de ejecución. La condición debe evaluarse en ambos casos de la misma manera.
Creo que la mejor respuesta es "¿en qué idioma está este ejemplo"?
La pregunta no especificó el idioma y está etiquetada tanto con 'C' como con 'C ++'. Una respuesta precisa necesita más información.
Es una pregunta de programación pésima, pero podría ser buena en el tortuoso departamento de "démosle al entrevistado suficiente cuerda para que se cuelgue o construya un columpio". El problema con ese tipo de preguntas es que generalmente se escriben y pasan de un entrevistador a otro hasta que llegan a personas que realmente no las entienden desde todos los ángulos.
Cree dos programas simples utilizando las formas sugeridas.
Reúna los códigos. Mira la asamblea y podrás juzgar, ¡pero dudo que haya diferencia!
Las entrevistas son cada vez más bajas.
Solo como un aparte (en realidad creo que cualquier compilador decente hará que esta pregunta sea discutible, ya que la optimizará) usando 0 == bandera sobre bandera == 0 evita el error tipográfico en el que se olvida uno de los = (es decir, si accidentalmente escribe flag = 0 se compilará, pero 0 = flag no lo hará), lo cual creo que es un error que todos han cometido en un momento u otro ...