A friend of mine posted this problem on Facebook the other day, and for the life of me I can't figure it out. He's writing a client and server using the cubesat protocol. For some reason when he casts the data member of the protocol struct to a pointer, his data appears to be mangled.
Client code snippet:
uint32_t data[3] = { 1234U, 5678U, 9101U };
memcpy(packet->data32, data, sizeof(data));
packet->length = sizeof(data);
csp_send(connection, packet, 1000);
Server code snippet:
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]);
Output this code produces:
Packet received on 15: 2182284498
Packet received on 15: 5678
Packet received on 15: 9101
Packet received on 15: 80904723, 372113408, 596443136
Output a casual reader of this code would expect:
Packet received on 15: 1234
Packet received on 15: 5678
Packet received on 15: 9101
Packet received on 15: 1234, 5678, 9101
After some fiddling he's told me that he gets the correct output if he doesn't cast the data32
member of the struct to a uint32_t*
.
From my own research, packet
is of type csp_packet_t
, which is defined as:
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;
The full header file is here.
This is GNU C, so zero-length arrays are allowed.
I do not know the word size or endianness of the architecture on either side.
So, simply put - what's going on here? Why does the cast matter?