🌟 C# enum과 비트 플래그 😋 🌟
안녕하세요. 박민성입니다. 🤗
오늘은 C#에 enum과 비트 플래그에 대해서 글을 쓰고자 합니다. 🤔
1. enum이란?
enum은 서로 관련된 상수 값들에 이름을 붙여 묶어두는 형식입니다.
public enum PlayerState
{
Idle,
Move,
Attack
}
이렇게 만들면 숫자 대신 정해둔 이름으로 사용할 수 있습니다.
장점은 그냥 숫자보다 가독성이 좋고 관련된 상태나 선택지를 하나의 타입으로 묶는 것입니다.
2. enum의 내부 값
enum의 각 항목은 내부적으로 정수 값을 가집니다.
public enum PlayerState
{
Idle, // 0
Move, // 1
Attack // 2
}
0부터 시작하여 1식 커지며 enum 값을 가지게 됩니다.
Debug.Log((int)PlayerState.Idle); // 출력 0
Debug.Log((int)PlayerState.Move); // 출력 1
Debug.Log((int)PlayerState.Attack); // 출력 2
기본 기반 형식은 int입니다.
값을 직접 지정할 수도 있습니다.
public enum PlayerState
{
Idle = 0,
Move = 10,
Attack = 20
}
만약에 일부만 값을 지정하면 다음 항목부터 이전 값에서 1씩 증가합니다.
public enum PlayerState
{
Idle = 5,
Move, // 6
Attack // 7
}
보통 값을 지정할 때는 저장 데이터와 값을 맞출 때나 비트 플래그를 만들 때 많이 사용됩니다.
enum을 정수로 변환할 수 있습니다.
PlayerState state = PlayerState.Attack;
int value = (int)state;
Debug.Log(value); // 2
enum 값을 정수로 바꾸려면 명시적 캐스팅을 사용합니다.
PlayerState state = (PlayerState)1;
Debug.Log(state); // Move
요런 식으로 정수를 enum으로 바꾸는 것도 가능합니다.
하지만.
이런 식으로는 많이 사용하진 않습니다.
왜냐하면 정의되지 않는 숫자도 캐스팅되기 때문입니다;;
public enum PlayerState
{
Idle,
Move,
Attack
}
PlayerState state = (PlayerState)100;
Debug.Log(state); // 100
enum은 이름이 붙은 정수 값이지만 런타임에서 정의되지 않은 숫자가 들어갈 수도 있다는 점이 보통 이렇게 사용되지 않다는 얘기입니다. 사용할 의미도 없고 진~~~~~~짜 만약에 사용하게 된다면 주의도 필요하니.... 정말 쓰지 않는 사용 방식입니다..
또한
public enum Result
{
Success = 0,
Complete = 0,
Fail = 1
}
이런 식으로 같은 값을 여러 이름에 줄 수 있지만.
의미가 헷갈릴 수 있으므로 특별한 이유가 있지 않다면 사용하지 않는 편이 좋습니다.
3. 비트 플래그란?
비트 플래그는 정수의 각 비트를 각각 하나의 옵션으로 사용하는 방식입니다.
enum은 보통 하나의 상태를 표현하지만 여러 옵션을 동시에 저장하고 싶을 때 비트 플래그를 사용할 수 있습니다.
[Flags]
public enum Element
{
None = 0,
Fire = 1,
Ice = 2,
Lightning = 4
}
이진수로 보면
None = 0000
Fire = 0001
Ice = 0010
Lightning = 0100
각 값이 서로 다른 비트 하나만 사용하고 있습니다.
그래서 여러 값을 겹치지 않고 조합할 수 있습니다.
그럼 만약에 Fire과 Ice를 둘 다 표현하고 싶으면 0011 = 3으로 Fire과 Ice를 표현할 수 있습니다.
그렇기 때문에 2의 거듭제곱을 사용합니다.
4. 1 << n의 의미
비트 값을 직접 적는 대신 시프트 연산자를 사용할 수 있어.
[Flags]
public enum Element
{
None = 0,
Fire = 1 << 0,
Ice = 1 << 1,
Lightning = 1 << 2,
Wind = 1 << 3
}
결과는
1 << 0 = 1
1 << 1 = 2
1 << 2 = 4
1 << 3 = 8
이런 식으로 나타납니다.
1 << n은 숫자 1의 비트를 왼쪽으로 n칸 이동시키는 것입니다.
5. | 로 플래그 합치기
비트 OR 연산자 |를 사용하면 여러 값을 합칠 수 있습니다.
Element element = Element.Fire | Element.Ice;
이진수로 보면 0001(Fire)+ 0010(Ice) = 0011으로 불과 얼음을 동시에 표현할 수 있습니다.
새 플래그를 추가할 때도 사용할 수 있습니다.
element |= Element.Lightning;
6. &로 플래그 확인하기
특정 플래그가 들어 있는지 확인하려면 &를 사용합니다.
if ((element & Element.Fire) != 0)
{
Debug.Log("불 속성 보유");
}
if ((element & Element.Fire) == Element.Fire)
{
Debug.Log("불 속성 보유");
}
이러면 비트 연산으로 &은 둘 다 1이어야 1이기 때문에 겹치지 않는다면 0이 나오기 때문에 가능합니다.
또한 HasFlag()도 사용할 수 있습니다.
if (element.HasFlag(Element.Fire))
{
Debug.Log("불 속성 보유");
}
다만 성능이 중요한 반복 구간에서는 직접 비트 연산을 사용하는 경우가 많습니다. 왜냐하면 HasFlag보다 비트 연산이 값이 싸기 때문입니다.
7. 플래그 제거하기
특정 플래그를 제거하려면 &와 ~를 함께 사용합니다.
element &= ~Element.Fire;
~은 비트 보수 연산자로서 0을 1로 1을 0으로 반전시키는 연산자입니다.
(~Element.Fire로 Fire 비트를 반전시키고 &로 Fire 비트만 끄는 겁니다.)
8. [Flags]는 무슨 역할을 할까요~?
[Flags]
public enum Element
[Flags]는 이 enum이 비트 조합 용도로 사용된다는 의도를 나타내는 어트리뷰트입니다.
[Flags]가 비트 연산을 가능하게 만드는 것은 아니며 없어도 |, & 연산은 가능하지만 문자열 출력과 디버깅 가독성이 좋아지고
enum이 조합 가능한 값이라는 의도를 알려주는 역할입니다.
오늘은 C#에 enum과 비트 플래그에 대해서 알아보았는데요~!
단순히 enum에 대해서만 알고 있었는데여 비트 플래그는 enum 찾아보면서 알게 되었는데요. 비트 플래그는 제가 만드는 갠프에 속성이 있기 때문에 사용할 듯싶습니다.
오늘의 노래 추천은
I Stereo Hearts - Gym Class Heroes이라는 곡입니다. ㅎㅎ
특히 0:44초부터 나오는 랩과 1분대 초까지 이어지는 부분이 좋았습니다.
내일은 더욱 알차게 보내고 작성해 보도록 하겠습니다.
봐주셔서 감사합니다. ☺️