[Solved] Dividing a bit string into three parts in C


The splitter() function here does the job you ask for. It takes quite a lot of arguments, unfortunately. There’s the value to be split (value), the size of the chunk at the least significant end of the value (p1), the size of the middle chunk (p2), and then pointers to the high, medium and low values (hi_val, md_val, lo_val).

#include <assert.h>
#include <inttypes.h>
#include <stdio.h>

static void splitter(uint32_t value, unsigned p1, unsigned p2, uint32_t *hi_val, uint32_t *md_val, uint32_t *lo_val)
{
    assert(p1 + p2 < 32);
    *lo_val = value & ((1U << p1) - 1);
    value >>= p1;
    *md_val = value & ((1U << p2) - 1);
    value >>= p2;
    *hi_val = value;
}

static void test_splitter(uint32_t value, int p1, int p2)
{
    uint32_t hi_val;
    uint32_t md_val;
    uint32_t lo_val;

    splitter(value, p1, p2, &hi_val, &md_val, &lo_val);
    printf("0x%.8" PRIX32 " (%2u,%2u,%2u) = 0x%.4" PRIX32 " : 0x%.4" PRIX32 " : 0x%.4" PRIX32 "\n",
            value, (32 - p1 - p2), p2, p1, hi_val, md_val, lo_val);
}

int main(void)
{
    uint32_t value;

    value = 0xFFFFFFFF;
    test_splitter(value, 9, 11);
    value = 0xFFF001FF;
    test_splitter(value, 9, 11);
    value = 0x000FFE00;
    test_splitter(value, 9, 11);

    value = 0xABCDEF01;
    test_splitter(value, 10, 6);
    test_splitter(value, 8, 8);
    test_splitter(value, 13, 9);
    test_splitter(value, 10, 8);

    return 0;
}

The test_splitter() function allows for simple testing of a single value plus the sections it is to be split in, and main() calls the test function a number of times.

The output is:

0xFFFFFFFF (12,11, 9) = 0x0FFF : 0x07FF : 0x01FF
0xFFF001FF (12,11, 9) = 0x0FFF : 0x0000 : 0x01FF
0x000FFE00 (12,11, 9) = 0x0000 : 0x07FF : 0x0000
0xABCDEF01 (16, 6,10) = 0xABCD : 0x003B : 0x0301
0xABCDEF01 (16, 8, 8) = 0xABCD : 0x00EF : 0x0001
0xABCDEF01 (10, 9,13) = 0x02AF : 0x006F : 0x0F01
0xABCDEF01 (14, 8,10) = 0x2AF3 : 0x007B : 0x0301

If any of the sections is larger than 16, the display gets spoiled — but the code still works.

In theory, the 1U values could be a 16-bit quantity, but I’m assuming that the CPU is working with 32-bit int. There are ways (UINT32_C(1)) to ensure that it is a 32-bit value, but that’s probably OTT. The code explicitly forces 32-bit unsigned integer values, and prints them as such.

solved Dividing a bit string into three parts in C