Bit banging on this level is not easy. I find it much easier to expand the data from binary bits to an array of bytes. This means an byte gets expanded to eight bytes, one byte for each of its bits. When you have this representation you can use indexes to access the array in a simple way. I do this often so I have a function to expand the bits and another to condense an array of bytes into a binary value of packed bits.
Here's how you can expand one byte into an array of bits. You can do this with data of arbitrary size by adding looping logic which I will leave for you to figure out.
using UCHAR = unsigned char;
const int BitsPerByte = 8;
void ExpandByteBits( UCHAR exp[], UCHAR bits )
{
for( int n = 0; n < BitsPerByte; ++n )
{
UCHAR mask = 1 << n;
exp[ n ] = bits & mask;
}
}
UCHAR value = 42;
UCHAR bits[ BitsPerByte ] = { 0 };
ExpandByteBits( bits, value );
If you have a 32-bit program then a standard integer will be 32-bits long or four bytes so you will need an array of four bytes and you need to call the function for each of the bytes, one at a time.
Now, whether this satisfies your complexity requirement - I don't know exactly because the problem requires additional logic which you will have to provide. You will have to evaluate that aspect of the program.
Hint : to deal with data that is multiple bytes in size (like a double) cast a pointer to the data into a pointer to a UCHAR and then access the bytes one at a time. Like this :
using UINT64 = unsigned long long;
UINT64 data = 4827262678;
UCHAR * pdata = (UCHAR *) & data;
UCHAR unpacked[ sizeof( UINT64 ) * BitsPerByte ];
since you know the size of that data you can write a loop to access each of its bytes. I will leave this to you because you need to figure this stuff out. I am not going to do it all for you.