그라운드 임베디드 유튜브 구독

노트 / C 언어

구조체, 공용체, 비트필드

레지스터 묶음과 통신 패킷을 구조체로 표현하고, 메모리 정렬과 패딩이 왜 생기는지 확인합니다.

GROUND EMBEDDED · 정리 노트C 언어 08구조체, 공용체, 비트필드 1struct { uint8_t a; uint32_t b; };// siz…

구조체

관련된 값을 하나로 묶습니다. MCU 헤더 파일은 주변장치의 레지스터를 주소 순서대로 구조체 멤버로 선언하고, 그 구조체 포인터를 주변장치 시작 주소에 맞춥니다. TIM2->CNT가 바로 이 방식입니다.

정렬과 패딩

32비트 CPU는 4바이트 값을 4의 배수 주소에 두려 합니다. 그래서 컴파일러가 멤버 사이에 빈 바이트를 넣습니다.

struct { uint8_t a; uint32_t b; };   // sizeof는 5가 아니라 8

통신 패킷을 구조체로 그대로 보내면 이 빈 바이트까지 나가서 상대가 엉뚱하게 해석합니다. 패킷은 바이트 단위로 직렬화하거나 packed 속성을 쓰되 정렬되지 않은 접근의 비용을 알고 씁니다.

공용체

같은 메모리를 여러 자료형으로 봅니다. float를 4바이트 배열로 쪼개 보낼 때 자주 씁니다.

비트필드

uint32_t en : 1;처럼 비트 단위로 멤버를 나눕니다. 읽기는 편하지만 비트 순서가 컴파일러마다 달라서 레지스터나 통신 포맷을 정의할 때는 마스크와 시프트를 쓰는 편이 안전합니다.