宏定义X-MACRO的高级应用(高阶版)
宏定义X-MACRO的高级应用(高阶版)
1. 结构体序列化问题
通常情况下,对于模块或者设备之间通信,往往是以字节流的方式来传输,而模块内部却要将这些字节流按某种数据结构来处理。这就存在,如何将数据结构(结构体)转换(序列化)成字节流,已经如何将字节流转换(反序列化)成数据结构的方法。
这不是很简单么?
tStrcut s;
unsigned char buff[100];
memcpy(buff, &s, sizeof(s)); // serial
memcpy(%s, buff, sizeof(s)); // de-serial
似乎,这也没什么毛病,非要挑毛病,那也只是结构体对齐的一点点问题。对于我们追求卓越的程序猿,还有什么更好的方法呢?
1.1 使用X-MACRO来构建
之前,我们学习了X-MACRO,何不用一下?
首先,我们定义一个宏:
#define EXPAND_STAR \
EXPAND_STAR_MEMBER(x, int) \
EXPAND_STAR_MEMBER(y, int) \
EXPAND_STAR_MEMBER(z, int) \
EXPAND_STAR_MEMBER(radius, double)
然后,在用这个宏定义结构体:
typedef struct
{
#define EXPAND_EXPAND_STAR_MEMBER(member, type) type member;
EXPAND_STAR
#undef EXPAND_EXPAND_STAR_MEMBER
} starStruct;
那么这个序列化和反序列化方法可以这样:
void serialize_star(const starStruct *const star, unsigned char *buffer)
{
#define EXPAND_STAR_MEMBER(member, type) \
memcpy(buffer, &(star->member), sizeof(star->member)); \
buffer += sizeof(star->member);
EXPAND_STAR
#undef EXPAND_STAR_MEMBER
}
void deserialize_star(starStruct *const star, const unsigned char *buffer)
{
#define EXPAND_STAR_MEMBER(member, type) \
memcpy(&(star->member), buffer, sizeof(star->member)); \
buffer += sizeof(star->member);
EXPAND_STAR
#undef EXPAND_STAR_MEMBER
}
如何打印结构体元素呢?元素中有int和double,打印方式是不一样的,于是,我们可以这样做:
#define print_int(val) printf("%d", val)
#define print_double(val) printf("%g", val)
void print_star(const starStruct *const star)
{
/* print_##type will be replaced with print_int or print_double */
#define EXPAND_EXPAND_STAR_MEMBER(member, type) \
printf("%s: ", #member); \
print_##type(st