Search code examples
ccharbytebitbitmask

Bitmask for exactly one byte in C


My goal is to save a long in four bytes like this:

unsigned char bytes[4];
unsigned long n = 123;

bytes[0] = (n >> 24) & 0xFF;
bytes[1] = (n >> 16) & 0xFF;
bytes[2] = (n >> 8) & 0xFF;
bytes[3] = n & 0xFF;

But I want the code to be portable, so I use CHAR_BIT from <limits.h>:

unsigned char bytes[4];
unsigned long n = 123;

bytes[0] = (n >> (CHAR_BIT * 3)) & 0xFF;
bytes[1] = (n >> (CHAR_BIT * 2)) & 0xFF;
bytes[2] = (n >> CHAR_BIT) & 0xFF;
bytes[3] = n & 0xFF;

The problem is that the bitmask 0xFF only accounts for eight bits, which is not necessarily equivalent to one byte. Is there a way to make the upper code completely portable for all platforms?


Solution

  • How about something like:

    unsigned long mask = 1;
    mask<<=CHAR_BIT;
    mask-=1;
    

    and then using this as the mask instead of 0xFF?

    Test program:

    #include <stdio.h>
    
    int main() {
        #define MY_CHAR_BIT_8 8
        #define MY_CHAR_BIT_9 9
        #define MY_CHAR_BIT_10 10
        #define MY_CHAR_BIT_11 11
        #define MY_CHAR_BIT_12 12
        {
            unsigned long mask = 1;
            mask<<=MY_CHAR_BIT_8;
            mask-= 1;
            printf("%lx\n", mask);
        }
        {
            unsigned long mask = 1;
            mask<<=MY_CHAR_BIT_9;
            mask-= 1;
            printf("%lx\n", mask);
        }
        {
            unsigned long mask = 1;
            mask<<=MY_CHAR_BIT_10;
            mask-= 1;
            printf("%lx\n", mask);
        }
        {
            unsigned long mask = 1;
            mask<<=MY_CHAR_BIT_11;
            mask-= 1;
            printf("%lx\n", mask);
        }
        {
            unsigned long mask = 1;
            mask<<=MY_CHAR_BIT_12;
            mask-= 1;
            printf("%lx\n", mask);
        }
    }
    

    Output:

    ff
    1ff
    3ff
    7ff
    fff