前几天,我的一个朋友在 Facebook 上发布了这个问题,而对于我的生活,我无法弄清楚。他正在使用 cubesat 协议编写客户端和服务器。由于某种原因,当他将协议结构的数据成员转换为指针时,他的数据似乎被破坏了。
客户端代码片段:
uint32_t data[3] = { 1234U, 5678U, 9101U };
memcpy(packet->data32, data, sizeof(data));
packet->length = sizeof(data);
csp_send(connection, packet, 1000);
服务器代码片段:
uint32_t *data = (uint32_t *)(packet->data32);
printf("Packet received on %i: %u\r\n", PORT, data[0]);
printf("Packet received on %i: %u\r\n", PORT, data[1]);
printf("Packet received on %i: %u\r\n", PORT, data[2]);
printf("Packet received on %i: %u, %u, %u\r\n", PORT, data[0], data[1], data[2]);
输出此代码产生:
Packet received on 15: 2182284498
Packet received on 15: 5678
Packet received on 15: 9101
Packet received on 15: 80904723, 372113408, 596443136
输出此代码的普通读者会期望:
Packet received on 15: 1234
Packet received on 15: 5678
Packet received on 15: 9101
Packet received on 15: 1234, 5678, 9101
经过一番摆弄后,他告诉我,如果他不data32
将 struct 的成员强制转换为 a ,他会得到正确的输出uint32_t*
。
根据我自己的研究,packet
是 type csp_packet_t
,定义为:
typedef struct __attribute__((__packed__)) {
uint8_t padding[CSP_PADDING_BYTES]; // Interface dependent padding
uint16_t length; // Length field must be just before CSP ID
csp_id_t id; // CSP id must be just before data
union {
uint8_t data[0]; // This just points to the rest of the buffer, without a size indication.
uint16_t data16[0]; // The data 16 and 32 types makes it easy to reference an integer (properly aligned)
uint32_t data32[0]; // - without the compiler warning about strict aliasing rules.
};
} csp_packet_t;
完整的头文件在这里。
这是 GNU C,因此允许使用零长度数组。
我不知道两边架构的字长或字节序。
所以,简单地说——这里发生了什么?为什么演员阵容很重要?