[C++] C++에서 사용되는 개념 9탄(열거형)

Patrick!·2023년 1월 8일
0
post-thumbnail

ENUM 에 대하여

지난번에 상수를 설정하다보면

const int SCISSORS = 1;
const int ROCK = 2;
const int PAPER = 3;

위에 작성된 것처럼 작성하기 마련이다.
하지만 의미 부여상으로 보면 같은 성격을 가진 존재들끼리 하나로 묶는 개념이 필요하다.

그래서 나타난 개념이 바로 'ENUM'이다.

ENUM 의 개념
enumerated type의 줄임말로 열거형이라고 부르기도 하는데 컴퓨터 프로그래밍에서 열거형(enumerated type, enumeration)은 요소, 멤버라 불리는 명명된 값의 집합을 이루는 자료형이다.

ENUM 통해 작성하면 다음과 같은 장점을 누릴 수 있다.

  • IDE의 지원을 받을 수 있다. 자동완성, 오타검증, 텍스트 리팩토리 등 허용 가능한 값들을 제한할 수 있다.
  • 리팩토링 시 변경 범위가 최소화 된다. 내용을 추가해도 Enum 코드만 수정하면 된다.
  • 확실한 부분과 불확실한 부분을 분리할 수 있다.
  • 문맥(Context)을 담을 수 있다.

그렇다면 위의 const 로 생성한 것을 ENUM으로 바꾸어보자!

enum ENUM_SPP
{
    ENUM_SCISSORS = 1,
    ENUM_ROCK,
    ENUM_PAPER
};

이렇게 작성된 ENUM은 const에 비해 초기값을 설정하지 않아도 된다. (const와 차이점)

ENUM에 선언한 변수들에 대한 값은 어떻게 결정되는가?

숫자를 지정 안하면 첫 값은 0부터 시작한다. (즉, ENUM_SCISSORS = 0; 이라는 의미이다.)
그 다음의 값들은 이전 값에 + 1이 진행된다.

여기서 처음 값을 정한다면? 그 다음 값들도 같이 이전 값에 + 1이 된 상태로 빌드가 된다.

그렇다면 여기서 ENUM에 대한 부분을 살펴보자

int input;

if (input = ENUM_SCISSORS) { cout << "SCISSORS" << endl; }

위처럼 ENUM_SCISSORS 로 작성된 부분에 제대로 된 ENUM_SCISSORS의 값이 들어가게 된다.

이는 메모리를 낭비하는 일도 없으며 const로 선언한 data를 사용하는 방법보다 좋은 부분을 보여준다.

하지만 현업에서는 상황에 따라서 const를 사용하는 경우도 있다보니 이렇게 간단하게 개념을 익히고 가자.

그렇다면 여기서 const와 enum의 명확한 쓰임새와 차이점에 대해 알아보자.

const 의 경우, 메모리에 저장될 때, 되지 않을때가 있다.

일반적으로 const는 빌드를 진행할 때, 메모리에 주소값이 지정되어 있지 않다.
F5를 눌러 확인해보면 [식은 lvalue 또는 함수 지정자여야 합니다.]로 출력될 것이다.

하지만 int main() 안에서
auto a = &SCISSORS; 이런 경우, SCISSORS의 주소값을 auto a 에 넣어줬기에
메모리에 담겨 있는 모습을 확인할 수 있다.

이를 조금 심화적으로 다루어 보자면 int main() 밖(data 영역)에
선언한 const int ~~ 들은 메모리에 올라가지 않고 실행될 때,

int main() 안에서 자신들이 쓰여진 부분에 자신들(변수)이 들어가는게 아니라
자신의 값(1,2,3)등이 바로 들어가는 경우가 생긴다.

또는 int main() 안(Stack 영역)
선언한 const int ~~ 들은 stack 영역에 올라가서 동작 방식으 달라질 수 있다.

또는 int main() 밖(data 영역)
선언한 const int ~~ 을 int main() 안에서
auto b = &ROCK; 처럼 선언한다면 이를 메모리에 할당하게 되는데,
이 방법은 위에서 알게된 방법과 다르게 메모리를 더 소모하는 방향으로 진행된다.
(즉, 메모리의 과소모 = 낭비가 이루어질 수 있는 방법이다.)

#이 붙은 개념 -> 전처리 지시문을 의미한다.

우리가 컴파일을 진행할 때, 1) 전처리 -> 2) 컴파일 -> 3) 링크
컴파일을 진행하기 전에 미리 컴파일 하기 쉽도록 거치는 단계 = 전처리

그럼 우리는 어디서 #을 사용하는 거지?!
우리는 CPP 파일을 만들 때, 항상 #include 을 작성한다.
iostream 의 내용을 전부 긁어서 여기에 붙여주세요!! 라는 의미로 받아들이면 된다.

위에서 간단한 예시로 알아본 결과
DEFINE_SCISSORS 로 작성된 부분을 1이라는 값으로 넣어서 진행해주세요!! 라는 의미로 쓰여진다고 보면 된다.

#define DEFIME_SCISSORS 1

const와 ENUM은 우리가 정수만 사용했었다. 놀랍게도 #define은 정수도 출력할 수 있다.

#define DEFIME_TEST cout << "HELLO, WORLD"<< endl;

#define을 그렇게 추천하지 않는 이유가 있다고 한다..

파일을 실행하면, 앞서 설명 했듯이 (우리가 컴파일을 진행할 때, 1) 전처리 -> 2) 컴파일 -> 3) 링크)
순서대로 진행이 된다. 그렇기에 전처리 단계에서 진행이 되는 #define을 디버깅해서 볼 때는, 결코 찾아볼 수 없다.

이유는 이미 컴파일을 진행할 당시 define에 정의한 변수들이 전부 define의 값으로 치환되어서 컴파일이 진행되었기에 이를 찾아볼 수 없는 것이다.

그렇기에 #define을 추천하지 않는 것이다.(물론 필요하고 적재적소인 부분에서는 사용하는 것이 맞다!)

profile
C++와 Unreal Engine / C#과 Unity / Katalon Studio를 통한 자동화 테스트 등을 하루하루 공부한 기록

0개의 댓글