3-6.열거형
3-6-가.정의
열거형(Enumeration)이란 변수가 가질 수 있는 가능한 값들을 나열해 놓은 타입이다. 어떤 변수가 가질 수 있는 값의 종류가 일정한 범위로 정해져 있다면 정수형 대신 열거형을 쓰는 것이 더 편리하다. 열거형 변수를 선언할 때는 enum 키워드를 사용한다.
enum { 멤버, 멤버, ... } 변수;
열거형으로 가능한 값들을 열거 멤버라고 하는데 { } 괄호안에 값의 이름을 나열하면 된다. 구체적인 예를 들어 보자.
enum { EAST, WEST, SOUTH, NORTH } mark;
mark라는 변수는 방향값을 기억하는데 가능한 값은 동서남북 넷 중 하나이다. mark에 값을 대입하거나 비교할 때는 열거 멤버를 사용한다.
mark=EAST; // mark에 EAST를 대입
if (mark==WEST) // mark가 WEST이면
열거형은 내부적으로 정수로 처리되며 각 열거 멤버는 0부터 1씩 증가하는 정수값을 가진다. 위 예에서 EAST는 0이고 WEST는 1이고 SOUTH, NORTH는 각각 2와 3이다. 컴파일러는 열거형의 멤버들이 어떤 정수값을 가지는지 기억해 두었다가 열거 멤버를 만나면 실제값을 적용한다. 열거형은 정수를 직접 사용하는 방식에 비해 다음과 같은 장점이 있다.
① 기억이 용이하다. 열거형 대신 정수형 변수를 대신 사용할 수도 있으나 이렇게 되면 각 정수의 의미가 무엇인지 사람이 일일이 기억해야 하는 불편함이 있다. 값이 10개 정도 된다면 무척 혼란스러울 것이다. 부서를 기억하는 변수 part가 있다고 하자. 이 변수를 정수형으로 선언한다면 각 부서에 대해 0은 총무부, 1은 영업부, 2는 인사부, 3은 경리부, .... 10은 관리부 등으로 의미를 정하고 외워야 하지만 열거형을 사용하면 그럴 필요가 없다. 사람은 숫자보다 문자를 더 잘 기억한다. 10개 정도가 아니라도 LEFT, RIGHT 두 개만 있어도 사람은 무척 혼란스러워한다.
② 소스의 가독성(Readability)이 높아진다. 즉, 읽기만 하면 어떤 의도로 작성된 소스인지 쉽게 파악할 수 있다. mark=3이라고 되어 있으면 3이 무슨 뜻인지 바로 알기 어렵지만 mark=NORTH라고 되어 있으면 북쪽을 대입했다는 것을 분명히 알 수 있다. 팀 작업을 할 때는 이런 가독성이 아주 중요하다.
③ 열거형은 정수형보다 안전하다. mark에 대입될 수 있는 값은 4가지중 하나로 제한되며 동서남북중 하나만 대입될 수 있다. mark를 정수형으로 선언한다면 이 변수에 5를 대입할 수도 있지만 열거형은 가능한 값 중 하나만 대입할 수 있기 때문에 이런 어처구니없는 실수를 컴파일러가 허락하지 않는다.
열거 멤버는 별도의 지정이 없으면 0부터 시작하는 정수값으로 정의되며 이어지는 멤버는 앞 멤버의 값+1이 된다. 만약 열거 멤버의 값을 특정한 값으로 분명히 지정하고 싶다면 =다음에 원하는 값을 직접 적어준다.
enum { EAST=5, WEST=10, SOUTH, NORTH} mark;
이렇게 하면 EAST는 5의 값을 가지면 WEST는 10의 값을 가진다. SOUTH, NORTH는 별도의 값 지정이 없으므로 WEST다음의 정수인 11, 12의 값을 가진다. 다음 열거형은 요일 타입을 정의한다. 요일의 가능한 값은 월요일~일요일까지 일곱가지밖에 없으므로 열거형으로 선언하기에 적당하다.
enum { mon, tue, wed, thr, fri, sat, sun } day;
이렇게 선언하면 mon이 0이 되고 tue부터 차례대로 1~6까지의 값을 가질 것이다. C는 항상 0부터 수를 세지만 사람은 1부터 세는 것에 더 익숙하기 때문에 첫 번째 멤버의 값을 1로 바꾸는 것이 더 합리적인 경우가 많다. 이럴 때 enum {mon=1, ... 으로 선언하면 월요일부터 일요일까지 1~7의 값을 가지게 된다.
열거 멤버는 일종의 명칭이므로 다른 변수명과 중복되어서는 안되며 유일한 이름을 가져야 한다. 한 열거형내에서 열거 멤버끼리 중복되는 것도 물론 허용되지 않는다. 따라서 다음과 같이 열거형을 선언하는 것은 잘못된 것이다.
enum { man, woman, man } human;
man이라는 멤버가 두 번 중복되어 있는데 이렇게 되면 human=man이라는 대입문이 0을 대입하라는 것인지 2를 대입하라는 것인지 애매해지게 된다. 언어는 애매해서는 안되므로 이런 식의 열거형 선언은 허용되지 않는다. 하지만 열거 멤버의 값은 중복되어도 상관없다.
enum { man=1, woman=2, girl=2 } human;
woman과 girl이 똑같은 값을 가지고 있지만 애매하지는 않으므로 이것이 문제가 되지는 않는다. 이 경우 woman과 girl은 일종의 동의어로 처리되며 human=woman 대입문과 human=girl 대입문은 둘 다 똑같이 human에 2를 대입하게 된다. 열거 멤버는 내부적으로 정수형으로 처리되므로 음수를 사용하는 것도 물론 가능하다.