(flag == 0) 또는 (0 == flag) 경우 어느 것이 더 빨리 실행합니까?
인터뷰 질문 : 빨리 실행됩니다 한 if (flag==0)
또는 if (0==flag)
? 왜?
나는 아직 정답을 발견하고 (그리고 이미 몇 가지) 주의 사항 : Nawaz는 사용자 정의 트랩을 지적했습니다 . 그리고 나는 많은 사람들이 그것을 선택해 서지 못한 것처럼 배열 최적화에 대한 훌륭한 토론을위한 공간을 제공하기 때문에 "어리석은 질문에 대한 급한 투표를 후회 한 것을 후회합니다. :)
정답은 :
flag
유형 은 무엇입니까?
경우에서 flag
실제로 사용자 정의 형식이다. 다음 어느 과부하 그런 operator==
가 선택 되었는지에 따라 다릅니다 . 그들이 동의 한 적이 지 않다는 것은 확실히 어리석은 것처럼 보일 수 있습니다.
flag
인 내장형 경우 둘 다 동일한 속도를 가져야합니다.
의 Wikipedia 기사 에서 x86
나는 (0이 아니라면 점프) 또는 이와 동등한 문장 에 대한 Jxx
지시에 내기를 걸었다 .if
JNZ
최적화가 해제 된 경우에도 컴파일러가 명확한 최적화를 놓친 것입니다. 이것은 들여다 보는 구멍 최적화 이 설계된 유형입니다 .
편집 : 다시 튀어 나와서 어셈블리를 추가합시다 (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과 비교됩니다. 두 번째 경우에는 == 연산자가 호출됩니다.
의심 스러울 때 그것을 벤치마킹하고 진실을 배우십시오.
속도면에서 정확히 동일해야합니다.
그러나 어떤 사람들은 (등등 비교 =
연산자) 대신 (할당 연산자) 를 쓰면 발생할 수있는 모든 오류를 피하기 위해 등식 비교 (소위 "Yoda conditionals")에서 상수를 왼쪽에 두는 데 사용합니다 ==
. 리터럴에 할당하면 컴파일 오류가 발생하므로 이러한 종류의 실수를 방지 할 수 있습니다.
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
{
}
반면에, 대부분의 사람들은 "Yoda conditional"이 이상하고 성가 시다고 생각합니다. 특히 적절한 컴파일러 경고를 사용하여 예방하는 오류 클래스를 발견 할 수 있기 때문입니다.
if(flag=0) // <--- warning: assignment in conditional expression
{
}
다른 사람들이 말했듯이 차이가 없습니다.
0
평가해야합니다. flag
평가해야합니다. 이 프로세스는 어느쪽에 배치 되든 동일한 시간이 걸립니다.
정답은 둘 다 같은 속도입니다.
심지어 표현 if(flag==0)
과 if(0==flag)
문자 같은 양의있다! 그들 중 하나가으로 작성 되었다면 if(flag== 0)
컴파일러는 파싱 할 추가 공간을 하나 갖게되므로 컴파일 시간을 지적 할 합법적 인 이유가있을 것입니다.
하지만 그런 것이 없기 때문에 다른 사람보다 빠를 이유가 전혀 없습니다. 이유가 있다면 컴파일러는 생성 된 코드에 매우 이상한 일을하고 있습니다.
어느 것이 빠른지 사용하는 == 버전에 따라 다릅니다. 다음은 ==의 두 가지 가능한 구현을 사용하는 스 니펫이며 x == 0 또는 0 == x 호출 여부에 따라 2 개 중 하나가 선택됩니다.
POD를 사용하는 경우 속도와 관련하여 정말 중요하지 않습니다.
#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);
}
글쎄, 나는 운동을 위해 OP에 대한 의견에서 말한 모든 것에 완전히 동의합니다.
컴파일러가 충분히 영리하지 않거나 (실제로 사용해서는 안 됨) 최적화가 비활성화 된 x == 0
경우 네이티브 어셈블리 jump if zero
명령어로 컴파일 0 == x
할 수있는 반면 숫자 값을보다 일반적 (비용이 많이 드는) 비교가 될 수 있습니다.
그래도 이런 식으로 생각하는 상사를 위해 일하고 싶지는 않습니다 ...
실행 속도면에서 분명히 차이가 없습니다. 두 경우 모두 동일한 방식으로 조건을 평가해야합니다.
가장 좋은 대답은 "이 예제는 어떤 언어로되어 있습니까?"입니다.
질문은 언어를 지정하지 않았으며 'C'와 'C ++'태그가 모두 붙어 있습니다. 정확한 답변에는 더 많은 정보가 필요합니다.
형편없는 프로그래밍 질문이지만, "인터뷰 대상에게 목을 매달거나 나무 그네를 만들 수있는 충분한 밧줄을 줍시다"부서에서는 좋은 질문이 될 수 있습니다. 이런 종류의 질문의 문제는 일반적으로 모든 각도에서 그것을 이해하지 못하는 사람들에게 도달 할 때까지 면접관에서 면접관에게 기록되어 전달된다는 것입니다.
제안 된 방법을 사용하여 두 개의 간단한 프로그램을 빌드하십시오.
코드를 조립하십시오. 어셈블리를보고 판단 할 수 있지만 차이가있는 것 같지 않습니다!
인터뷰는 그 어느 때보 다 낮아지고 있습니다.
제쳐두고 (실제로 괜찮은 컴파일러 가이 질문을 할 것이라고 생각합니다. 최적화 할 것이기 때문에) 0 == flag over flag == 0을 사용하면 = 중 하나를 잊어 버리는 오타를 방지합니다. flag = 0 그것은 컴파일되지만 0 = flag는 그렇지 않습니다), 나는 모든 사람들이 한 지점 또는 다른 지점에서 실수를 저지른 것이라고 생각합니다 ...
차이가 있다면 컴파일러가 더 빠른 것을 선택하는 것을 막는 것은 무엇입니까? 따라서 논리적으로 차이가있을 수 없습니다. 아마도 이것이 면접관이 기대하는 것입니다. 실제로 이것은 훌륭한 질문입니다.
참고 URL : https://stackoverflow.com/questions/4624536/which-one-will-execute-faster-if-flag-0-or-if-0-flag
'IT' 카테고리의 다른 글
제목을 8 방향으로 분류 할 때 체인이 if / else if 경우를 피하는 방법은 무엇입니까? (0) | 2020.07.28 |
---|---|
점이 선의 오른쪽인지 (0) | 2020.07.28 |
GitHub에 Android Studio 프로젝트를 추가하는 방법 (0) | 2020.07.28 |
NSArray보다 NSSet을 사용하는 것이 더 좋은 경우는 언제입니까? (0) | 2020.07.28 |
Spring 3.0 식 언어로 @Scheduled (fixedDelay)를 매개 변수화하는 방법은 무엇입니까? (0) | 2020.07.28 |