C Language Basic

C Language [핵심정리] - 33

cCcode 2021. 6. 29. 17:14

1. 구조체 비트 필드 사용하기

지금까지 구조체의 멤버는 각 자료형의 크기만큼 공간을 차지했습니다. 하지만 구조체 비트필드를 사용하면 구조체 멤버를 비트 단위로 저장할 수 있습니다. 

 

C99 표준에서는 비트 필드로 사용할 수 있는 자료형을 Bool, signed int, unsigned int, int로 규정되어있습니다만, 대부분의 컴파일러에선 실수 자료형을 제외한 모든 정수 자료형을 사용할 수 있습니다. 비트 필드는 다음과 같이 :(콜론) 뒤에 비트 수를 지정하면 됩니다. + 일반적으로 비트필드에는 부호없는 자료형을 주로 사용합니다.

비트 수 지정하기
비트 필드 사용하기
비트 필드 사용하기 - 2
결과

이처럼 비트 필드의 각 멤버는 최하위 비트부터 차례대로 배치 되기 때문에 코드 주석에 적은 것처럼 비트 끝에서부터 가져올 비트를 정하는겁니다. 그럼 비트 필드 구조체의 크기는 어떻게 될까요?

비트필드 구조체 크기
결과

비트 필드의 멤버를 unsigned int로 선언했으므로 구조체의 크기는 4가 나옵니다. 그리고 비트를 지정할 때는 해당 자료형 크기에서 가져오는 것이기 때문에 자료형보다 큰 비트 수는 지정할 수 없습니다. 여기서는 unsigned int(4byte = 32bit)이므로 32bit 이상 지정하는 게 불가능하겠네요.

자료형을 넘는 비트 지정
에러 메세지

사실 전에 배운 구조체와 공용체를 혼용하며 비트 필드를 사용할 수 있으나 내용이 어렵고, 실제로 잘 쓰이는 편은 아니라 비트 필드 구조체에 대한 설명은 여기까지 하겠습니다.

 

1. 열거형 사용하기

열거형은 구조체가 변수의 선언을 좀더 간단하게 만들기 위해 사용된 것처럼 정수형 상수를 조금 더 간단히 선언하기 위해 사용되었습니다. 우리는 상수를 선언할 때 const 키워드를 붙여 선언하는데요. 한 두개까지는 그럴 수도 있다 넘어가지만 그 수가 수십, 수백개의 변수에 이른다면 정말 생각만해도 끔찍하지 않나요.

 

열거형은 enum 키워드를 사용하여 선언하며, 해당 키워드 명enumeration(열거)에서 가져왔습니다.

열거형 정의

열거형 또한 다른 구조체나 공용체처럼 정의만으로 사용할 순 없고 따로 변수를 선언해서 사용합니다.

○ enum 열거형 명 변수 명;

enum 사용
결과

열거형의 값은 처음에 초깃값만 지정해주면 그 다음 값들은 1씩 더해가면 자동으로 할당됩니다. (할당하지 않는다면 0부터 시작) 보통 열거형을 사용할 때는 처음에 초깃값만 지정하지만, 연속적이지 않은 불규칙한 값을 지정하고 싶다면 모든 열거형 에 하나하나 할당하면 됩니다. 열거형은 구조체처럼 typedef 키워드로 별칭을 지정 또는 익명 열거형정의하고 선언과 동시에 변수선언할 수 있습니다. 다만 이 역시 구조체와 동일하게 정의되기 때문에 설명은 생략하겠습니다.

 

+ 제가 처음에 열거형은 정수형 상수를 간단히 선언하기 위해 사용되었다고 했잖아요? 여러분들도 알고 있는 것처럼 상수는 한번 선언한 이후 값의 변경이 불가능합니다. 그래서 저는 enum으로 정의된 멤버들 또한 값 변경이 불가능할 줄 알았거든요. 근데 그건 또 아니더라고요. 

상수 확인
결과

이처럼 변수에 할당된 enum의 멤버는 수정 가능하지만, enum 멤버 자체수정이 불가능하네요.

enum 멤버
멤버 수정
에러 메세지

이 과정에서 다른 구조체공용체와는 다르게 enum 열거형의 멤버는 일반 변수처럼 바로 접근이 가능하다는 걸 알았습니다.

 

열거형을 switch 분기문이나 for 반복문을 이용해 활용할 수 있습니다.

1) switch 분기문

switch 분기문 이용
결과

이걸 이용한다면 일종의 매크로 봇과 비슷한 기능을 구현할 수도 있겠네요. switch 분기문에서는 정수와 문자인 경우에만 분기를 나눌 수 있는데 이에 딱 맞는게 enum 열거형 입니다.

2) for 반복문 

for 반복문 이용
결과

member_count 라는 변수를 이용해 enum의 최대 개수를 구할 수 있습니다. 다만 이 때, 초깃값은 0이 되어야 합니다. 왜냐하면 member_count 전체 개수를 알기위해 넣은 멤버 이므로 제외해줘야 합니다. 따라서 다음 조건을 만족해야 합니다.

1) 숫자를 세는 멤버가 가장 마지막에 위치해 있어야 한다.

2) 숫자를 세는 멤버의 개수를 (전제 개수에)포함하면 안된다 ( ex) member_count - 1 or 초깃값을 0으로 시작)