简体   繁体   中英

Initializing a struct with the contents of a std::vector<unsigned char>

This seems like something that should be simple and straightforward, but Google turns up very little.

What's a clean, modern (C++11) way of initializing a simple file header struct like the following

typedef struct FooHeader {
    uint8_t    FooCount;
    uint8_t    BarCount;
    uint32_t   BazOffsets[4];
} FooHeader;

with the data contained in a std::vector<unsigned char> ? Is it a good idea to create a sub vector and cast its data to the header struct type, or?

To avoid running into packing, alignment and endianness issues, it is best to read the data at the byte level (on almost all modern hardware, you can assume 8-bit bytes, but packing often changes between compilers (or even just between different compilation flags) and both big and little endian computers are still common).

This means that your best bet is something like:

FooHeader load_FooHeader(std::vector<unsigned char> const &dat) {
    static_assert(
        std::numeric_limits<unsigned char>::digits == 8,
        "Assumes 8-bit bytes");

    FooHeader retv;

    retv.FooCount = dat[0];
    retv.BarCount = dat[1];

    //Start at the fifth byte, to allow for padding.
    //If you want to use a packed format, use index = 2;
    std::size_t index{4};
    for (std::size_t i{0}, iend{4}; i < iend; ++i) {
        retv.BarOffsets[i] = 0;
        //Adjust ordering depending on desired endianness.
        //Currently uses little endian.
        for (std::size_t j{0}, jend{4}; j < jend; ++j) {
            retv.BarOffsets[i] |= dat[index + i*4 + (3-j)] << (j*8);
        }
    }

    return retv;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM