처럼, 다른 쪽을 해제 직렬화한다, 대신 직렬화한다 (쓰기시) 및 구조화 주석을 바이트 버퍼로 /에서 역 직렬화 (읽기시)합니다.
이렇게하는 방법에는 여러 가지가 있습니다. 예를 들어, 인라인 함수 (C99 static inline
), 전 처리기 매크로, 각 필드 당 개별 함수, 필드를 비트 팩하는 일반 함수 등이 있습니다.
가장 일반적인 옵션은 내부 구조에서 바이트 배열을 압축하거나 압축을 해제하는 것입니다. 예를 들어, 내부적으로 사용되는 구조의 경우
struct mbxh {
INT8U channel:4;
INT8U priority:4;
INT16U length;
INT16U address;
INT8U array[4];
};
static void pack_mbxh(unsigned char *const dst, const struct mbxh *src)
{
dst[0] = src->channel | ((src->priority) << 4);
dst[1] = src->length >> 8;
dst[2] = src->length;
dst[3] = src->address >> 8;
dst[4] = src->address;
dst[5] = src->array[0];
dst[6] = src->array[1];
dst[7] = src->array[2];
dst[8] = src->array[3];
}
static void unpack_mbxh(struct mbxh *dst, const unsigned char *const src)
{
dst->channel = src[0] & 15U;
dst->priority = (src[0] >> 4) & 15U;
dst->length = (src[1] << 8) | src[2];
dst->address = (src[3] << 8) | src[4];
dst->array[0] = src[5];
dst->array[1] = src[6];
dst->array[2] = src[7];
dst->array[3] = src[8];
}
이것은 바이트 순서를 지정하는 것이 쉽기 때문에 특히 유용합니다. 위의 예에서는 length
및 address
필드에 대해 빅 엔디안 또는 네트워크 바이트 순서를 사용합니다.
대상 시스템이 매우 RAM 제약이있는 경우 전처리 매크로를 사용하여 "압축"필드에 직접 액세스하는 것이 좋은 옵션입니다. 이렇게하면 메모리는 적지 만 CPU 리소스는 많이 사용됩니다. (이하 "포장"분야도 여기에 빅 엔디안 또는 네트워크 바이트 순서를 사용합니다.) 실제로
#define mbxh_get_channel(data) ((data)[0] & 15U)
#define mbxh_get_priority(data) ((data)[0] >> 4)
#define mbxh_get_length(data) ((((INT16U)(data)[1]) << 8) | ((INT16U)(data)[2]))
#define mbxh_get_address(data) ((((INT16U)(data)[3]) << 8) | ((INT16U)(data)[4]))
#define mbxh_get_array(data, i) ((data)[i])
#define mbxh_set_channel(data, value) \
do { \
(data)[0] = ((data)[0] & 240U) | ((INT8U)(value)) & 15U); \
} while (0)
#define mbxh_set_priority(data, value) \
do { \
(data)[0] = ((data)[0] & 15U) | (((INT8U)(value)) & 15U) << 4); \
} while (0)
#define mbxh_set_length(data, value) \
do { \
(data)[1] = ((INT16U)(value)) >> 8; \
(data)[2] = (INT8U)(value); \
} while (0)
#define mbxh_set_address(data, value) \
do { \
(data)[3] = ((INT16U)(value)) >> 8; \
(data)[4] = (INT8U)(value); \
} while (0)
#define mbxh_set_array(data, index, value) \
do { \
(data)[(index)] = (INT8U)(value); \
} while (0)
, 당신은 많은 이러한 구조를 가지고 특히, 이들의 조합이 작동합니다.
static INT8U get4u_lo(const INT8U *const ptr)
{
return (*ptr) & 15U;
}
static INT8U get4u_hi(const INT8U *const ptr)
{
return (*ptr) >> 4;
}
static INT16U get16u(const INT8U *const ptr)
{
return (((INT16U)ptr[0]) << 8) | ptr[1];
}
static void set4u_lo(INT8U *const ptr, INT8U val)
{
*ptr &= 240U;
*ptr |= val & 15U;
}
static void set4u_hi(INT8U *const ptr, INT8U val)
{
*ptr &= 15U;
*ptr |= (val % 15U) << 4;
}
static void set16u(INT8U *const ptr, INT16U val)
{
ptr[0] = val >> 8;
ptr[1] = val;
}
다음, 당신은을 사용하여 당 구조 현장 접근을 쓰기, 낮은 니블, 높은 니블 또는 16 비트 필드 : 첫째, 각 유형 필드의에 액세스하는 일부 소형 함수를 작성 도우미 기능 이상 :
#define mbxh_get_channel(data) get4u_lo((INT8U *)(data)+0)
#define mbxh_get_priority(data) get4u_hi((INT8U *)(data)+0)
#define mbxh_get_length(data) get16u((INT8U *)(data)+1)
#define mbxh_get_address(data) get16u((INT8U *)(data)+3)
#define mbxh_get_array(data, i) ((data)[5+(i)])
#define mbxh_set_channel(data, v) set4u_lo((INT8U *)(data)+0, (v))
#define mbxh_set_priority(data, v) set4u_hi((INT8U *)(data)+0, (v))
#define mbxh_set_length(data, v) set16u((INT8U *)(data)+1, (v))
#define mbxh_set_address(data, v) set16u((INT8U *)(data)+3, (v))
#define mbxh_set_array(data, i, v) ((data)[5+(i)] = (v))
이 답변에서 모든 예에서와 같이, 위가 너무 데이터에 대한 빅 엔디안 또는 네트워크 바이트 순서를 사용합니다. channel
은 네 개의 하위 비트에 있고 priority
은 첫 번째 데이터 바이트의 네 개의 상위 비트에 있습니다.
전반적으로 데스크톱 응용 프로그램의 경우 첫 번째 옵션 (함수 호출 당 구조체 변환)과 내부 구조를 사용하는 것이 좋습니다. 마이크로 컨트롤러 및 기타 제한된 메모리 케이스의 경우이 최신 버전을 사용하는 것이 좋습니다.
(위의 코드 중에 테스트하지 않습니다 당신은 오타 나 버그 나 기타 오류를 발견하면. 댓글에서 나를 알려 주시기 바랍니다, 그래서 위의 예제 코드를 수정할 수 있습니다.)
구조에 비트 필드를 사용하여 당신을 축 어적으로 네트워크에 작성하려는 계획은 가능한 최악의 유스 케이스입니다. serialize/de-serialize 할 코드를 작성해야 각 바이트를 제어 할 수 있고 컴파일러가 수행하는 작업에 의존하지 않아도됩니다. – unwind
비트 채우기가 절대로 (또는 항상) 있습니다. 패딩은 바이트 만 고려합니다. 비트 필드는 전체 바이트 수를 차지합니다. 'channel'은 1 바이트입니다. –
@unwind - 맞습니다. 직렬화/역 직렬화하고 싶습니다. 그러나 크기와 변수가 다른 10 가지 구조가 있다면 일반적인 방법으로이를 수행하는 방법은 무엇입니까? 대안을 생각해 낼 수 있습니까? 지금까지의 모든 대답은 그 구조와 관련이 있습니다 ... 그러나 어떤 구조에 대해서도 일반적인 것을 얻는 것은 제가 생각할 수없는 것입니다 (나의 두뇌의 한계). –