Search code examples
cbit-manipulationbitwise-operatorsunionsbit-fields

Bit fields for reading from H/W registers


I want to read the 2nd, 5th and the 6th bit from a 32-bit register. I have decided to use struct bit fields to store them. Is the following data structure correct?

struct readData
{
    int unwanted:1;
    int reqbit1:1;
    int unwanted1:2;
    int reqbit2:2;
    int unwanted2:26;
};

I'm not sure about how the bit fields are created. I'm going to use an API that will copy bytes from the h/w register to this structure directly. In that case, will reqbit1 contain the 2nd bit? As per my understanding, the compiler allots the first bit to an int variable and the 2nd bit is alloted to another int variable and so the reqbit1 won't have any data read from the register. Isn't the following union more suitable for this situation?

union readData
{
    struct readBits
    {
        bool unwanted:1;
        bool reqbit1:1;
        xxx unwanted1:2;
        short reqbit2:2;
        xxx unwanted2:26;
    };

    int regValue;
};

If this is right, what should I declare unwanted2 as?


Solution

  • From the C standard: "The order of allocation of bit-fields within a unit (high-order to low-order or low-order to high-order) is implementation-defined."

    So you shouldn't use bitfields where the order matters.

    Use explicit masking and shifting instead:

    reqbit1 = (w >> 1) & 1;    
    reqbit2 = (w >> 4) & 3;
    

    or

    reqbit1 = (w & 0x00000002) >> 1;    
    reqbit2 = (w & 0x00000010) >> 4;
    

    and for the other direction

    w = (reqbit1 << 1) | (reqbit2 << 4);
    

    The "unwanted" parts are typically named reserved1 and so on.