SSAFY

[SSAFY 임베디드 C] 비트 필드 연산 (Eclipse vs Ubuntu)

딸기토끼0623 2024. 9. 28. 11:47

1. 비트필드 연산이란?

비트 필드 연산이란, 하나의 변수안에서도 그 안의 내용을 비트단위로 쪼개서 쓸 수 있는 연산이다.

#include <stdio.h>
#include <stdint.h>

union UNIO{
        uint8_t data;
        struct {
                uint8_t a: 1;
                uint8_t b: 2;
                uint8_t c: 5;
        };
} u1;

int main(){
        u1.data = 87;
        printf("a: %u\n", u1.a);
        printf("b: %u\n", u1.b);
        printf("c: %u\n", u1.c);

}
DEC: 87
BIN 

c, b, a / 10, 3, 1

최종 DEC 결과값
c, b, a 순으로 쪼개진다.

2. 만약 비트수가 선언된 타입의 크기를 넘어간다면? 

그런데, 다음과 같이 비트를 넘어가는 순간, 오류가 발생한다.

#pragma pack(1)

#include <stdio.h>
#include <stdint.h>

union UNIO{
	uint16_t data;
	struct {
		uint8_t a: 3;
		uint8_t b: 2;
		uint8_t c: 5;
	};
} u1;

int main(){
	u1.data = 87;
	printf("a: %u\n", u1.a);
	printf("b: %u\n", u1.b);
	printf("c: %u\n", u1.c);
	return 0;
}

 

DEC: 87
우리가 생각하는 BIN 구조

c, b, a / 2, 2, 7

최종 DEC 결과값

하지만 이번엔 c 가 0이 나와버렸다!!


3. 왜 이런 현상이 발생하는가?

처음엔 이유를 찾는라 한참을 해맸지만, 곧 Eclipse로 메모리를 조회하며 이유를 알 수 있었다.

실제 메모리 주소

u1.c 의 주소지가 1밀려있는걸 알 수 있다.

따라서 실제 메모리 구조는 아래와 같은걸 알 수 있다.

실제 BIN 구조
c, b, a / 0, 2, 7

4. 결과 / 주의점

결과적으로 Eclipse C 에서는 비트필드 연산자가 uint8_t 와 같이 앞에 선언된 변수의 할당 크기를 넘어가면, 다음 주소지로 변수를 밀어버린다는 것을 알 수 있다.

5. 그런데!!

반드시 꼭 밀어버리는 것도 아닌듯 하다..

서로 다른 결과값

Windows10 Eclipse (MinGW): 7, 2, 0
Ubuntu Gcc: 7, 2, 2

즉, Ubuntu Gcc에서는 우리가 예상했던 BIN 값이 나왔다.

이에 대한 이유와 설명은 다음 포스팅에서 다루어 보도록 하겠다.. (왜지..?)