c++gccflexible-array-memberpacked

Portable alternative for packed structures with a flexible array member


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.


Solution

  • [[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.)