我的一个 friend 前几天在 Facebook 上发布了这个问题,但我终究无法弄明白。他正在使用 cubesat 协议(protocol)编写客户端和服务器。出于某种原因,当他将协议(protocol)结构的数据成员转换为指针时,他的数据似乎被破坏了。
客户端代码片段:
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
成员转换为 uint32_t*
,他会得到正确的输出。
根据我自己的研究,packet
是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;
完整的头文件是here .
这是 GNU C,所以 zero-length arrays are allowed .
我不知道两边架构的字长或字节顺序。
所以,简单地说 - 这里发生了什么?为什么 Actor 很重要?
最佳答案
2182284498
是0x821304D2
,其中0x04d2
是1234
,其余可能是数据包。更多,不知道 csp_send
和相应的接收器看起来如何(即:显示更多代码)是不可能知道的。
而这一行:memcpy(packet->data32, data, sizeof(data));
实际上是缓冲区溢出错误...因为你没有为 packet 分配足够的字节->data32
关于c - 为什么将数组中的 a 转换为指针会破坏我的数据?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22683117/