I currently have a integer value that was read from an input file as a hexadecimal. I need to divide the 32 bit bitstream into three separate parts in order to manipulate it. The desired output is below:
desired output:
In this, V is my input value, left is the first X1 digits, next is the digits between X1 and X2, and last is the digits from X2 to the end. There is a constraint that each subsection must be greater than 0 in length.
What makes this difficult is that the location where I am splitting x varies (X1 and X2 can change)
Is there a good way to split these up?
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.