인터뷰 질문 : 한 빨리 실행됩니다 if (flag==0)
또는 if (0==flag)
? 왜?
답변
나는 아직 정답을 보지 못했습니다 (그리고 이미 일부가 있습니다) 경고 : Nawaz는 사용자 정의 트랩을 지적했습니다 . 그리고 “가장 어리석은 질문”에 대해 서둘러 찬성 투표를 한 것을 후회합니다. 많은 사람들이 제대로 이해하지 못한 것 같고 컴파일러 최적화에 대한 좋은 토론의 여지를 제공합니다. 🙂
정답은:
flag
유형 은 무엇입니까 ?
경우 여기서 flag
실제로 사용자 정의 형식이다. 그런 다음 어떤 과부하 operator==
가 선택 되었는지에 따라 다릅니다 . 물론 그것들이 대칭 적이 지 않다는 것은 어리석은 것처럼 보일 수 있지만, 그것은 확실히 허용되며, 이미 다른 학대를 보았습니다.
flag
가 내장 된 경우 둘 다 동일한 속도를 가져야합니다.
에 대한 Wikipedia 기사 에서 x86
나는 진술 에 대한 Jxx
지침을 if
기대할 것 JNZ
입니다.
최적화가 꺼져 있어도 컴파일러가 그러한 명백한 최적화를 놓치는 것은 의심 스럽습니다. 이것은 Peephole Optimization 이 설계된 유형입니다 .
편집 : 다시 시작되었으므로 어셈블리를 추가해 보겠습니다 (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
}
IR을 읽는 방법을 모르더라도 자명하다고 생각합니다.
답변
GCC 4.1.2를 사용하는 amd64에 대한 동일한 코드 :
.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
답변
버전에는 차이가 없습니다.
type
of 플래그가 사용자 정의 유형이 아니라 일부 내장 유형 이라고 가정하고 있습니다. Enum은 예외입니다! . enum을 내장 된 것처럼 취급 할 수 있습니다. 사실, 그것의 값은 내장형 중 하나입니다!
사용자 정의 유형 (제외 enum
) 인 경우 대답은 전적으로 연산자를 오버로드 한 방법에 따라 달라집니다 ==
. ==
각 버전에 대해 하나씩 두 개의 함수를 정의 하여 오버로드 해야합니다!
답변
전혀 차이가 없습니다.
하지만 다음과 같이 할당 / 비교 오타 제거를 참조하여 인터뷰 질문에 답할 때 점수를 얻을 수 있습니다.
if (flag = 0) // typo here
{
// code never executes
}
if (0 = flag) // typo and syntactic error -> compiler complains
{
// ...
}
예를 들어 C 컴파일러가 전자 ( flag = 0
)의 경우 경고하는 것은 사실이지만 PHP, Perl 또는 Javascript 또는 <insert language here>
.
답변
속도면에서 전혀 차이가 없습니다. 왜 있어야합니까?
답변
플래그가 사용자 정의 유형일 때 차이가 있습니다.
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;
}
}
첫 번째 경우 (0 == s)에서 변환 연산자가 호출되고 반환 된 결과가 0과 비교됩니다. 두 번째 경우에는 == 연산자가 호출됩니다.
답변
의심 스러울 때 그것을 벤치마킹하고 진실을 배우십시오.