c언어에서는 기본적으로 1,2,4,8바이트 순으로 2의 지수가 증가하는 흐름으로 값을 저장할 수 있는 변수가 있습니다.

하지만 필요에 따라 3바이트 6바이트 짜리 데이터가 필요할 때도 있습니다.

그래서 이번에는 3바이트, 6바이트 데이터를 만드는 것을 해보도록 하겠습니다.

 

https://dojang.io/mod/page/view.php?id=653

 

C 언어 코딩 도장: 75.3 여러 줄을 묶어서 매크로로 정의하기

지금까지 숫자 한 개나 코드 한 줄을 매크로로 정의해서 사용했습니다. 그럼 여러 줄을 매크로로 만들 수 있지 않을까요? #define은 줄바꿈이 일어날 때 \를 사용하여 여러 줄을 매크로로 만들 수 �

dojang.io

우선 제 코드를 이해하기 위한 기본적인 지식입니다.

매크로를 여러줄 사용하기 위해서 \를 줄 끝에 가져가면 다음줄에도 매크로 정의를 이어서 사용할 수 있습니다. 마지막 줄엔 하지 않아도 됩니다.

 

<3바이트 값>

우선 integer로 값을 입력 받은후 3바이트 값에 값을 넣어보도록 하겠습니다. 

저는 3바이트 값을 uint8_t arr[3] 와 같은 식으로 구현하였습니다.

uint8_t를 모르신다면 char와 같다 생각하시면 됩니다.

여기서 static inline은 함수 속도를 아주 조금 빠르게 만드는데

네트워크에서 몇초에 수천 수만번 사용되는 함수라면 그 조금의 차이도 크기 때문에 사용합니다.

static inline void
intTo3bytes(int num, uint8_t* arr)
{
	arr[0] = (uint8_t)(num & 0x000000ff);
	arr[1] = (uint8_t)((num & 0x0000ff00) >> 8);
	arr[2] = (uint8_t)((num & 0x00ff0000) >> 16);
}

num은 3바이트에 넣을 값 그리고 arr는 3바이트 배열입니다.

4바이트로 값을 입력 받지만 가장 높은 1바이트 쪽 데이터는 버려지게 됩니다.

논리 연산자를 이용해서 각각 바이트 값을 추출하여 배열에 담는 식으로 3바이트 값에 값을 저장합니다.

 

하지만 위와 같이 3바이트 값을 저장하면 읽을 때는 읽는 방법또한 구현해 주어야합니다.

다음은 3바이트를 인티저로 바꿔서 읽는 방법을 구현한 매크로입니다.

 

#define bytes3ToInt(n1, n2, n3) ((uint32_t)(n3 & 0xff) << 16) | \
				((uint32_t)(n2 & 0xff) << 8)  | \
				((uint32_t)(n1 & 0xff)) 

위와 같이 배열에 저장된 순서에 따라 값의 순서를 8바이트 부터 그리고 16바이트부터 준 다음 논리 연산자로 합치는 매크로를 통해서 3바이트 값을 정수처럼 읽을 수 있도록 만들어 보았습니다.

 

그리고 이번에는 6바이트 입니다 3바이트를 만들 수 있으면 6바이트는 거져먹기죠

 

#define bytes6ToInt(n1, n2, n3, n4, n5, n6) ((uint64_t)(n6 & 0xff) << 48)  | \
						((uint64_t)(n5 & 0xff) << 32)  | \
						(uint64_t)(n4 & 0xff) << 24)   | \
						((uint64_t)(n3 & 0xff) << 16)  | \
						((uint64_t)(n2 & 0xff) << 8)   | \
						((uint64_t)(n1 & 0xff)) 

 

static inline void
longTo6bytes(long long num, uint8_t* arr)
{
	arr[0] = (uint8_t)(num & 0x00000000000000ff);
	arr[1] = (uint8_t)((num & 0x000000000000ff00) >> 8);
	arr[2] = (uint8_t)((num & 0x0000000000ff0000) >> 16);
	arr[3] = (uint8_t)((num & 0x00000000ff000000) >> 24);
	arr[4] = (uint8_t)((num & 0x000000ff00000000) >> 32);
	arr[5] = (uint8_t)((num & 0x0000ff0000000000) >> 40);
}

매크로로 만들고 보니 실제 배열 하나하나 저렇게 값을 넣는건 불편하니 매크로를 활용한 함수를 사용하는게 좋을 것 같아서 추가적으로 소개하고 끝내겠습니다.

 

static inline uint64_t
bytes6Tolong(uint8_t * arr)
{
	uint64_t num = _bytes6ToInt(arr[0], arr[1], arr[2], arr[3], arr[4], arr[5]);
	return num;
}

static inline uint32_t
bytes3ToInt(uint8_t* arr)
{
	uint32_t num = _bytes3ToInt(arr[0], arr[1], arr[2]);
	return num;
}

 

+ Recent posts