본문 바로가기
이론 공부 내용 정리/알고리즘

c/c++ switch/case문에 대해 실수한 사항

by mazayong 2022. 7. 31.

일반적으로 switch/case문에서 string을 쓸 수 없다.
그렇다면 왜 사용할 수 없는지 짧게 이론적으로 정리해 보려 한다.(필자가 까먹지 않기 위함으로)


c++에서 switch/case문에서 string을 왜 사용하지 못할까?

우선 switch 명령은 case가 많을수록 이론상 if문과의 성능 차이가 기하급수적으로 벌어지게 되어 있다.
여기서 이론상인 이유는 if문의 경우에도 비교하는 대상 중 어느 한 쪽이 상수라면 자동으로 점핑 테이블을 만들어 switch - case처럼 동작하기 때문이다.


잠깐 if문과 switch 문의 내부적 차이를 비교해보자.
if문은 각 경우마다 값을 비교하므로 최악의 경우는 모든 case에 대해 값을 비교하는 (어셈블리에서 CMP 연산)을 한다.
if문은 switch 연산을 실행할 때마다 CMP 연산의 수가 증가한다.


switch문은 구문을 실행할 때 점핑 테이블을 생성하는데, 이 때 case 값에 따라 점핑 테이블의 값이 달라진다. 그래서 case에 변수가 들어가면 안되는 것이다. 이 case 값들은 case별로 명령이 위치한 주소를 의미한다.
그러므로 switch문은 case에 따라 CMP 연산 횟수가 증가하는 것이 아니라서 성능은 영향을 받지 않는다.
그러므로 case 값들의 크기가 크지 않아야 하고, 값들이 순차적으로 정렬되고, 값 끼리의 차이가 크지 않을 때 가장 효율적이다.


그래서 상수가 아닌 경우는 점핑 테이블 생성이 어려워진다.
점핑 테이블을 쓰는 것은 시간이 오래 걸리는 테이블 생성 작업을 한 후 1번의 비교로 원하는 곳에 찾아가 작업하겠다는 성능을 기대하는 것이다.
(즉, 시간복잡도는 O(1)로 줄이길 원하는 것이다.)
그러나 변수가 case에 들어가면 일반적인 if문으로 구현되는 것이다. 이 때 switch문에 대한 CMP 연산식은 다음과 같다.

EIP = EIP + jmptable[nIDX]

변수가 case에 가능할 경우, 테이블은 기하급수적으로 커지며 변수가 상수가 아닌 경우는 nIDX값이 산출되지 않아 저런 식으로 불가능하고, 연결리스트 등을 써야 하므로 if문을 사용하는 것이다.


그래서 이 문제를 해결하기 위해 해시맵 등을 사용해 자체적으로 라이브러리를 구현해 사용하기도 한다.

참고
https://oojjrs.tistory.com/25
https://qa.apthow.com/archives/9610?amp=1
https://modoocode.com/16