我在C中有一个1字节的pragma压缩结构,我想复制到一个字节数组中以进行序列化,以便通过串行端口发送。
#pragma pack(push, 1)
typedef struct {
uint8_t ck_a;
uint8_t ck_b;
} UBXChecksum_t ;
#pragma pack(pop)
将其序列化为字节数组的最佳方法是什么,我应该只使用memcpy()
吗?
void writeStructToArray(const void* inStruct,
const uint16_t inLenStruct,
uint8_t* const outArray)
{
memcpy(outArray, inStruct, inLenStruct);
}
还是更好地使用逐字节复制进行指针类型转换?
void writeStructToArray(const void* inStruct,
const uint16_t inLenStruct,
uint8_t* const outArray)
{
for(uint16_t i = 0; i < inLenStruct; i++)
{
outArray[i] = ((uint8_t*)inStruct)[i];
}
}
答案 0 :(得分:5)
正如卡米尔·库克(Kamil Cuk)所说,您的两个建议几乎相同,但可能存在速度差异。
另一种选择是使用联合:
typedef struct {
uint8_t ck_a;
uint8_t ck_b;
} UBXChecksum_t ;
union convert {
UBXChecksum_t checksum;
char buffer[sizeof UBXChecksum_t];
};
UBXChecksum_t checksum;
union convert converter;
converter.checksum = checksum;
passArrayToSomeFunction(converter.buffer, sizeof(converter.buffer));
您不必复制数据即可将其转换为数组。您可以将指针传递给结构(如有必要,将其传递给char*
或void*
),并将结构大小传递给将数据发送到串行端口的函数。示例:
typedef struct {
uint8_t ck_a;
uint8_t ck_b;
} UBXChecksum_t ;
int sendData(void *buf, size_t size);
UBXChecksum_t checksum;
/* ... */
int rc = sendData(&checksum, sizeof(checksum));
所有这些变体将结构的内部表示形式发送为二进制数据。通常,“序列化”被理解为一种将数据转换为与平台无关的格式的方法。
如果接收系统是相同类型并且使用相同的编译器,则发送二进制数据结构将起作用。当接收系统使用不同的字节顺序或不同的数据类型大小时,您可能会遇到问题。
在您的情况下,您具有两个uint8_t
值的结构,因此大小是固定的,字节顺序也不成问题。
如果结构的要求是匹配指定的二进制数据协议,并且可以准备在必要时处理字节顺序,则可以发送二进制数据。
答案 1 :(得分:1)
memcpy()将不考虑系统的字节序。因此,如果Sender是大字节序,而接收者是小字节序,那么对于结构变量值,接收者将是一个冲突。
使用第二种方法,您知道在发送方准备字节流的方式,因此在接收端也可以相应地接收以确保适当的结构变量值。
如果系统的字节序相同,并且字节序无关紧要,则与循环分配字节值相比,这两种方法均能达到目的,并且memcpy()会更快。