IT

(flag == 0) 또는 (0 == flag) 경우 어느 것이 더 빨리 실행합니까?

lottoking 2020. 7. 28. 07:43
반응형

(flag == 0) 또는 (0 == flag) 경우 어느 것이 더 빨리 실행합니까?


인터뷰 질문 : 빨리 실행됩니다 한 if (flag==0)또는 if (0==flag)? 왜?


나는 아직 정답을 발견하고 (그리고 이미 몇 가지) 주의 사항 : Nawaz는 사용자 정의 트랩을 지적했습니다 . 그리고 나는 많은 사람들이 그것을 선택해 서지 못한 것처럼 배열 최적화에 대한 훌륭한 토론을위한 공간을 제공하기 때문에 "어리석은 질문에 대한 급한 투표를 후회 한 것을 후회합니다. :)

정답은 :

flag유형 무엇입니까?

경우에서 flag실제로 사용자 정의 형식이다. 다음 어느 과부하 그런 operator==가 선택 되었는지에 따라 다릅니다 . 그들이 동의 한 적이 지 않다는 것은 확실히 어리석은 것처럼 보일 수 있습니다.

flag인 내장형 경우 둘 다 동일한 속도를 가져야합니다.

Wikipedia 기사 에서 x86나는 (0이 아니라면 점프) 또는 이와 동등한 문장 에 대한 Jxx지시에 내기를 걸었다 .ifJNZ

최적화가 해제 된 경우에도 컴파일러가 명확한 최적화를 놓친 것입니다. 이것은 들여다 보는 구멍 최적화 이 설계된 유형입니다 .

편집 : 다시 튀어 나와서 어셈블리를 추가합시다 (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


버전에는 차이가 없습니다.

typeof 플래그가 사용자 정의 유형이 아니라 일부 내장 유형 이라고 가정합니다 . 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

반응형