memcpy copies memory one byte(*) at a time, so it is immune to
alignment issues.
If you have a uint_16 pointer (say), and it is pointing at an odd address, then there are NO guarantees as to what happens when you try and dereference that pointer.
I've seen all these happen.
- it just works
- it works with an expensive trap into the OS to "do the right thing"
- the lsb is silently truncated to zero and it reads the wrong data for you.
- the OS traps the alignment exception and kills your program dead.
(*) many implementations detect compatible alignments and copy words or longs whenever possible.
Writing memcpy() is trivial, as is writing your own versions of ntohs() for example.
> If that byte is the last byte of a buffer, and var is of size 2 (16 bits, in this particular case), then what's the difference of using an equal sign to copy the 16 bits or the memcpy?
If it is the last byte, then both are wrong anyway.
Both would be accessing a memory location which is undefined.
You're not going to solve this with simple 1-line casting magic. You need to step back and design a proper stream access function which takes your stream and returns the next 'n' bits as you require.
Code:
struct streambuf {
uint8_t *buff; // the buffer
size_t buffsize; // number of bytes in buff
size_t byteoffset; // initially 0
uint8 bitoffset; // initially 0
};
int readbits ( streambuf *sb, int nbits, uint32_t *result );
So if you're at the last byte, and you try and read say 13 bits, it returns some kind of error diagnostic.