29

C 언어의 switch 문장에서 숫자 값만 사용할 수 있다는 것을 알았 기 때문에 if-else의 무리와 더 깊은 차이가 있어야한다고 생각했습니다. Visual C++에서 스위치는 어떻게 컴파일되고 최적화되고 빠릅니까?

그러므로 나 자신에게 물었다 :

  • switch 런타임 속도의 측면에서 if-elseif-elseif 다른가 (방법), 시간 최적화 및 일반 컴파일 컴파일? 저는 주로 여기 MSVC에 대해 말하고 있습니다.

답변

35

스위치는 종종 어떤 코드를 실행할지 알아 내기 위해 점프 테이블로 컴파일되거나 불가능한 경우 컴파일러가 비교 순서를 재 배열하여 이진 검색을 수행 할 수 있습니다 값 중 (로그 N 비교). if-else 체인은 선형 검색입니다 (비록 모든 관련 값이 컴파일 시간 정수 정수인 경우 컴파일러는 원칙적으로 유사한 최적화를 수행 할 수 있습니다).

+0

+1 좋은 답변입니다. 또한 if-then-elseif 체인을 폄하하기 위해이 기회를 활용할 것입니다. 둘 이상의 'else if'는 DDD (Design Deficit Disorder)의 표식입니다. –

+5

VisualC++ 용 [실제 C++ 스위치 구현] (http://www.codeproject.com/Articles/100473/Something-You-May-Not-Know-About-the-Switch-Statem)이 있습니다. –

+0

이것이 가능하다면 최적화되지 않았다면 지금은 좋을 것입니다. – Lothar

8

switch 문은 종종 컴파일러 최적화의 일반적인 소스입니다. 즉, 처리 방법은 컴파일러에서 사용하는 최적화 설정에 따라 다릅니다.

switch 문을 컴파일하는 가장 기본적인 (최적화되지 않은) 방법은 if ... else if ... 문 체인으로 처리하는 것입니다. 이 방법은 빠른

if (condition1) goto label1; 
if (condition2) goto label2; 
if (condition3) goto label3; 
else   goto default; 
label1: 
    <<<code from first `case statement`>>> 
    goto end; 
label2: 
    <<<code from first `case statement`>>> 
    goto end; 
label3: 
    <<<code from first `case statement`>>> 
    goto end; 
default: 
    <<<code from `default` case>>> 
    goto end; 
end: 

이유 중 하나 인 조건문 내부의 코드가 작기 때문에 (너무 작은 명령어 캐시가있다 : 컴파일러 스위치를 최적화하는 일반적인 방법은 같은 것을 볼 수 이는 jump table로 변환하는 것입니다 조건부가 잘못 예측 된 경우의 벌칙). 또한 "폴스 스루"사례는 구현하기가 더 쉽습니다 (컴파일러는 goto end 문을 사용하지 않습니다).

컴파일러는 포인터의 배열 (레이블로 표시된 위치까지)을 만들어 점프 테이블을 더 최적화 할 수 있으며 전환하는 값을 해당 배열의 인덱스로 사용할 수 있습니다. 이렇게하면 전환 조건이 사례 중 하나와 일치하는지 여부를 확인하는 데 필요한 것을 제외한 거의 모든 조건문이 코드에서 제거됩니다.

중첩 된 점프 테이블은 생성하기가 어렵고 일부 컴파일러는 생성을 거부하기도합니다. 따라서 최대한 최적화 된 코드가 중요한 경우 switch을 다른 switch 안에 중첩하지 마십시오. MSVC가 중첩 된 switch es를 처리하는 방법을 100 % 확신하지는 않지만 컴파일러 설명서에서 알려야합니다.

+0

참고 : 최적화의 이점이 코드에 크게 의존하기 때문에 if-else 트리와 비교하여 스위치 성능과 관련된 특정 수치는 언급하지 않았습니다. 최적화에서 얼마나 많은 개선이 이루어지고 있는지를 알려주는 유일한 방법은 두 가지 방법으로 코드를 작성하고 각 코드를 실행하는 데 걸리는 시간을 측정하는 것입니다. – bta

+13

주어진 코드는 *** 점프 테이블이 아닙니다. 그것은 그 문제에 대해 어떤 테이블도 대표하지 않습니다. 그러나 Wikipedia에 대한 링크는 올바른 예를 제공합니다. – dualed

관련 문제