Search code examples
cbitramendianness

C how to read middle bits?


Please note my comments, the question is still unanswered.

I have the following which I can't change:

unsigned long addr=142;
u16 offset_low, offset_middle;
u32 offset_high;

I want to set offset_low for low 16 bits, offset_middle for mid 16 bits and offset_high for higher 32 bits of addr.

So I wrote:

offset_low = addr & 0xFFFF;
offset_middle = addr & 0xFFFF0000;
offset_high = addr & 0xFFFFFFFF0000;

Is this right? Is there any clear way to do it instead of wiriting so many F?

Why I think it's not right?

I am working with little endian, so when doing addr & 0xFFFF0000; I will get the mid bits but with zeros and it may load the zeros instead of non-zeroes.


Solution

  • For your purpose you must shift the masked values:

    unsigned long addr = 142;  // 64-bit on the target system
    uint16_t offset_low = addr & 0xFFFF;
    uint16_t offset_middle = (addr & 0xFFFF0000) >> 16;
    uint32_t offset_high = (addr & 0xFFFFFFFF00000000) >> 32;
    

    Note that since you extract exactly 16 and 32 bits to variables with the same size, masking can be omitted:

    uint64_t addr = 142;
    uint16_t offset_low = addr;
    uint16_t offset_middle = addr >> 16;
    uint32_t offset_high = addr >> 32;
    

    The order of bytes in memory (little endian vs big endian) is irrelevant for this question. You could read the specific parts from memory using this knowledge, reading the first 2 bytes for offset_low, the next 2 for offset_middle and the next 4 for offset_high, but extracting from the full 64-bit value is performed the same for both architectures.