将结构复制到字节数组

标签 c arrays struct pragma-pack

我在 C 中有一个 1 字节编译指示打包结构,我想将其复制到一个字节数组中以用于序列化目的,以便通过串行端口发送。

#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];
  }
}

最佳答案

正如 Kamil Cuk 评论的那样,您的两个提案几乎相同,只是速度可能存在差异。

另一种选择是使用 union :

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 值的结构,因此大小是固定的,字节顺序不是问题。

如果对结构的要求是匹配指定的二进制数据协议(protocol)并且您准备好在必要时处理字节顺序,则可以发送二进制数据。

关于将结构复制到字节数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54552564/

相关文章:

c - 理解C中的别名

c# - 如何在struct中初始化char数组

c++ - 我可以在不使用点运算符的情况下访问结构内部的结构吗?

c - SIMULINK 保持信号的先前值

c - 如何将参数传递给我的应用程序,其中包括 gdb 上的 - 符号?

c - 分配给缓冲区时 fgets 泄漏

c++ - 具有 4 个维度的 std::vector 的性能

java - 数组和类的空指针异常 - Java

json - 如果具有相同的对象,则在 Golang 中初始化嵌套结构定义

c - typedef 结构、循环依赖、前向定义