4 ms·
The important thing to remember, it's just a sequence of bits (and if that's a multiple of 8 then you can look at it as a sequence of bytes instead). Byte bound
by rkangel 4y ago
The important thing to remember, it's just a sequence of bits (and if that's a multiple of 8 then you can look at it as a sequence of bytes instead). Byte boundaries are just a way of looking at the result.
You get the bits in the order you ask for in the expression, and then it encodes each valuee as you ask. Note that the default encoding is big endian, so the value 0xFF00 comes out as the bit sequence 1111111100000000 wherever it is.
Now converting from a C-struct you absolutely do have to think about byte order, but erlang has you there too. Let's say you've got this:
#pragma pack(1)
struct {
uint16_t a;
uint8_t b;
uint8_t c;
uint32_t d;
};
Then all you do is:
<<a::16-native, b::8, c::8, d::32-native>> = my_block_of_data
And then all of your values (a, b, c, d) will be correct.
As I said above, erlang defaults to encoding/decoding each value as big-endian (e.g. <<0xFF00::16>> is equivalent to <<0xFF00::16-big>>. This is the default because big endian is used for the vast majority of comms protocols (in that context it's also called 'network byte order'). When interpreting values in memory though it can be either, depending on your processor (although mostly -little these days). Using -native as yoru endianness means "use big or little as appropriate for my processor". It's also a good signal that you're interpreting something from memory (as supposed to a protocol).
- throwawaymaths 4y agoI'm not talking about byte-sized data though. It's bit-sized, that's tough, especially when it crosses byte boundaries.