I have a struct
typedef struct {
uint8_t type; // 1B -> 1B
uint16_t hash; // 2B -> 3B
uint16_t id; // 2B -> 5B
uint32_t ip; // 4B -> 9B
uint16_t port; // 2B -> 11B
} Data;
and some binary data (which is a stored instance of Data on disk)
const unsigned char blob[11] = { 0x00, 0x00, 0x7b, 0x00, 0xea, 0x00, 0x00, 0x00, 0x59, 0x01, 0x00 };
I want to "read" the blob into my struct, the first byte 0x00 corresponds to type, the second and third byte 0x00, 0x7b correspond to hash, etc.
I can't just do Data *data = (Data *)blob, since the actual size of Data will probably be bigger than 11 Bytes (Faster RAM access or something. Not relevant here.) The point is sizeof(Data) == 16 and the representation in RAM may be different than the compact one on disk.
So how can I "import" my blob into a Data struct without having to use memcpy for every attribute? Aka what's nicest/simplest solution for this in C?
Since you cannot rely on the data layout in the file to match that of the in-memory structure, standard C does not provide an alternative to working member by member.
But reading the data from disk is potentially a different question from reading it from an array. I suppose you imagine reading one or more whole raw records into memory and then copying from there in some way, but if you can rely on the sizes and endianness of the individual fields matching between structure and disk then you could consider this:
That lets the stream handle the buffering (which it will, unless you disable that), relieves you of counting bytes, and is pretty clear. Five calls to
fread()might be a bit more expensive than five tomemcpy(), but you're unlikely to notice the difference next to the cost of opening the file and transfering data from it.If you do need to populate the structure from an in-memory array containing raw bytes from the file, however, then per-member
memcpy()is the most portable way. And quite possibly more efficient than you think.