I got a cstring, originating from a call from gzread. I know the data is blocks, and each block is consisting of an unsigned int, char, int and unsigned short int.
So I was wondering what the standard way of splitting this cstring into the appropriate variables is.
Say the first 4 bytes, is a unsigned int, the next byte is char, the next 4 bytes is signed int, and the last 2 bytes are unsigned short int.
//Some pseudocode below which would work
char buf[11];
unsigned int a;
char b;
int c;
unsigned short int d;
I guess I could memcpy, with appropriate offsets.
memcpy(&a, buf, sizeof(unsigned int));
memcpy(&b, buf+4, sizeof(char));
memcpy(&c, buf+5, sizeof(int));
memcpy(&d, buf+9, sizeof(unsigned short int));
Or is it better to use some bitoperators? Like shifting and masking.
Or would it be better to gzreading all 11 bytes directly into some struct, or is that even possible? Is the memory layout of a struct fixed, and will this work with gzread?
If you pack the struct (read up on __packed__ attribute), you can rely on the order and that the members are non-aligned. Hence, you could read into a struct directly. However, I'm not sure about the portability of this solution.
Otherwise, use pointer magic and casting like so:
char *buffer;
int a = *(reinterpret_cast<int*> (buffer))
unsigned short b = *(reinterpret_cast<unsigned short*> (buffer + sizeof(int)))
You need to make sure that the byte order of the file matches the processor architecture you're running your code on. If, for instance, the integers are written to file with most significant byte first and your processor uses least significant byte first order, you're getting garbage for results.
If you want to make your code portable from one architecture to another, you should wrap all read and write operations for integers behind macros or inline functions that manage the byte order for you depending on the target processor architecture.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With