51. 비트필드(bit-field)의 레이아웃과 부호
난이도 중내 리뷰 · C++
해설 · C++
해설 — 비트필드(bit-field)의 레이아웃과 부호
난이도: 중상
요약
비트필드는 여러 필드를 하나의 기반 정수 타입 안에 비트 단위로 채워 넣는다. 크기와
배치는 기반 타입·패킹·정렬로 정해지고, 상당 부분이 구현 정의다. 특히 폭 1의
signed 비트필드는 -1 과 0 만 표현할 수 있어 s1 = 1 이 -1 로 읽히는 함정이 있다.
실행 결과(예측; g++ x86-64 기준)
sizeof(A)=1
sizeof(B)=2
sizeof(C)=4
a: 1 5 15
b: 9 4000
c.s1=-1 c.s4=7
c.s4(-8)=-8
핵심 개념 / 단계별
- sizeof(A)=1:
A는 1+3+4 = 8비트를uint8_t(1바이트) 하나에 담는다. 세 필드가 한 바이트에 정확히 들어가 크기는 1. - sizeof(B)=2:
type(4) +len(12) = 16비트 =uint16_t하나. 크기 2, 정렬 2. - sizeof(C)=4: 기반 타입이
int(4바이트)다. s1+s4 는 5비트뿐이지만, 비트필드 객체의 크기·정렬은 기반 타입을 따르므로 struct 크기는 최소sizeof(int)=4. - a: 1 5 15: 각 필드 폭에 값이 들어맞는다(1<2, 5<8, 15<16).
+a.x는uint8_t를 정수로 승격해 문자가 아닌 숫자로 출력하기 위한 단항 +. - b: 9 4000:
type=9(4비트, <16),len=4000(12비트, <4096) 모두 표현 가능. - c.s1=-1: 폭 1의 signed 비트필드는 부호 비트 1개뿐 → 표현 가능한 값은
{0, -1} 뿐이다.
s1=1은 그 범위 밖이라 비트 패턴1이 부호 비트로 해석되어 -1. - c.s4=7 / c.s4=-8: 폭 4의 signed 는 2의 보수로 -8..7. 7 과 -8 모두 표현 가능해 그대로 나온다.
흔한 오해·함정
- 부호 지정 누락:
int a:1;같이 폭 1 signed 를 "0/1 플래그"로 쓰면 값이 -1 로 나온다. 플래그엔unsigned(또는uint8_t) 비트필드를 써야 한다. (그냥int : n의 부호성 자체도 일부 맥락에서 구현 정의였던 역사가 있어 명시적signed/unsigned권장.) - 비이식성(구현 정의):
- 필드가 기반 타입 내에서 어느 끝(LSB/MSB)부터 채워지는지(비트 순서),
- 필드가 저장 단위 경계를 넘을 때의 패킹/패딩,
int비트필드의 기본 부호성,- 서로 다른 컴파일러/ABI/엔디안 간 배치. → 그래서 비트필드를 그대로 네트워크/파일 포맷에 쓰면 안 된다. 이식 가능한 와이어 포맷은 명시적 시프트·마스크로 직렬화한다.
- 오버플로 대입: 필드 폭을 넘는 값 대입은 unsigned 는 하위 비트만, signed 는 구현 정의. 범위 검증을 코드가 책임져야 한다.
면접 포인트
- 비트필드 크기·정렬은 기반 타입이 지배한다(비트 합이 작아도 sizeof 는 기반 타입 배수).
- 폭 1 signed 비트필드 = {0,-1} — 플래그엔 unsigned.
- 비트필드 배치는 구현 정의라 와이어 포맷엔 부적합; 직렬화는 시프트/마스크로.