Suppose we were writing a C++ network application using UDP sockets. We needed to pass a not-so-small pack of data, so we used this kind of structure, making sure the byte order is the network one:
struct [[gnu::packed]] datagram {
uint64_t timestamp;
uint8_t type;
uint32_t temperatures[60]; // whatever, just an example
uint8_t raw_data[];
};
We were using GNU GCC, so we took advantage of non-standard C++ features such as
We needed a packed structure since we don't want padding in between, as this may be architecture-dependent, and our network program may run on different architectures.
Then, after a year, it may come out that we need to support a non-GCC compiler, which doesn't support those.
Is it possible to do this in standard C++?
Of course, I know we could simply use a uint8_t buffer[SOME_SIZE]
and memcpy every part of the datagram, but this sounds like a great way to create horrible, really ugly code.
[[gnu::packed]]
is a terrible way to do serialization between arbitrary architectures. There are still big-endian machines out there.
The right way to do this is to define a serialization format in terms of octets, and then convert between an octet stream (to or from the UDP socket), and a nicely arranged structure.
There are many libraries which make this straightforward. We use protobuf
at work; a previous employer had a home-brewed solution. (Note that a request for a recommendation for such a library is explicit off-topic for Stack Overflow.)