1
struct packet_format {
    uint32_t field_a;
    uint8_t  field_b;
    uint16_t field_c;
    uint32_t field_d;
    uint16_t field_e;
    uint8_t  field_f;
};

uint32_t size_of_packet = 14;
uint8_t *data_to_transmit = malloc(size_of_packet);
struct packet_format *s = (struct packet_format *)data;

s->field_a = 1;
s->field_b = 2;
s->field_c = 3;
s->field_d = 4;
s->field_e = 5;
s->field_f = 6;

sendto(... data_to_transmit, size_of_packet ...)

Due to structure padding, the data transmitted (data_to_transmit) is not guaranteed to be correct (in the format of the structure declared), right? So, what is the best way to put data in data_to_transmit in the right format? Will I need to memcpy every field of the structure separated?

Edit: little mistake on title

  • Yes copying by hand (memcpy, et al.) is probably the best way to ensure total control over transmission. – Jean-Baptiste Yunès Jan 23 '17 at 16:37
  • Just send the struct contents separately, on the receiver side read them separately and put them back into the struct. So even if on the receiver side structs are padded differently it will work. – Jabberwocky Jan 23 '17 at 16:38
  • Send each member separately – zoska Jan 23 '17 at 16:38
  • 2
    Related: http://stackoverflow.com/questions/30945121/dealing-with-data-serialization-without-violating-the-strict-aliasing-rule – Eugene Sh. Jan 23 '17 at 16:41
  • Sending the struct directly could also break endianess. – rom1v Jan 23 '17 at 16:50
  • Re-order the fields, widest to narrowest and then transit without the potential end padding. – chux - Reinstate Monica Jan 23 '17 at 17:26
  • Compiler specific solutions exist, but to keep things portable I suspect `memcpy` is your best bet. If you're able/prepared to target a specific compiler, like GCC, you can use `struct __attribute__((__packed__)) packed_format {}` for example – Elias Van Ootegem Jan 23 '17 at 18:38

1 Answers1

2

Search for compiler #pragmas, maybe it has an option to avoid padding.

But this will not be compatible on other compilers.

It is unavoidable to do it the "hard" way. For each data type, create a function that builds a packet from the data, and an opposite function that parses the packet into a data structure. No shortcuts here.

Israel Unterman
  • 13,158
  • 4
  • 28
  • 35