Home > OS >  Copy least most significant bits from an int to a long in C
Copy least most significant bits from an int to a long in C

Time:12-10

I am trying to copy the 8 least significant bits from an int to a given position in an unsigned long. My first approach was v1 = (v1 & ~0xf) | (v2 & 0xf); where v1 is the long and v2 the int. However, this would copy it at the very end and I am not sure how to modify it to be able to copy these 8 bits to any position in the long. Thanks for your help!

CodePudding user response:

Well, here is the simple function you need:

#include <iostream>


void moveAByte( unsigned long int& destinationLong, const int& sourceInt,
                const std::size_t destByteOffset, const std::size_t sourceByteOffset )
{
    uint8_t* const firstByteAddressOfLong { reinterpret_cast<uint8_t* const>( &destinationLong ) };
    const uint8_t* const firstByteAddressOfInt { reinterpret_cast<const uint8_t* const>( &sourceInt ) };

    *( firstByteAddressOfLong   destByteOffset ) = *( firstByteAddressOfInt   sourceByteOffset );
}

int main( )
{
    unsigned long int v1 { 0x12'34'56'78 }; // a sample number
    int v2 { 0x19'ab'cd'ef }; // another sample number

    const std::size_t destByteOffset { 3 }; // Here choose between 0, 1, 2 ,3
    const std::size_t sourceByteOffset { 0 }; // the same here

    std::cout << '\n';

    std::cout << "Before copying the byte " << sourceByteOffset << " of v2 to byte " << destByteOffset << " of v1" << "\n\n"
              << std::showbase << std::hex << "v1 address: " << &v1 << " --> " << "v1 value: " << v1 << '\n'
                                           << "v2 address: " << &v2 << " --> " << "v2 value: " << v2 << '\n';

    std::cout << std::dec << '\n' << "------------------------------------------------------" << "\n\n";

    moveAByte( v1, v2, destByteOffset, sourceByteOffset ); // source byte located in v2 is copied to destination byte located in v1

    std::cout << "After copying the byte " << sourceByteOffset << " of v2 to byte " << destByteOffset << " of v1" << "\n\n"
              << std::showbase << std::hex << "v1 address: " << &v1 << " --> " << "v1 value: " << v1 << '\n'
                                           << "v2 address: " << &v2 << " --> " << "v2 value: " << v2 << '\n';

    return 0;
}

Sample output:


Before copying the byte 0 of v2 to byte 3 of v1

v1 address: 0x8504fffc78 --> v1 value: 0x12345678
v2 address: 0x8504fffc7c --> v2 value: 0x19abcdef

------------------------------------------------------

After copying the byte 0 of v2 to byte 3 of v1

v1 address: 0x8504fffc78 --> v1 value: 0xef345678
v2 address: 0x8504fffc7c --> v2 value: 0x19abcdef

As can be seen, in this example, the least significant byte of v2 which is ef is copied to the most significant byte of v1 which was 12 but now it's ef too.

Using the function moveAByte you can easily copy any byte from v1 to any position in v2.

Note: This code only works on little-endian machines and not on big-endian ones.

Note: On my platform (Windows), long is 4 bytes. On macOS and Linux it's 8 bytes. So don't forget to take this into account if you're on macOS or Linux.

CodePudding user response:

Let's create a bitmask so that we can extract 8 least significant bits. If we calculate then we get 255 as our bit mask(11111111). Then, suppose you want to place those 8bits in the third place, so we can use (<<) operator for shifting to our desired position.

long ans=(long)((var&bitmask)<<pos);

CodePudding user response:

Bit shifting is what you need, check this. Basically, 0x1 << 2 add two zeros at the right of the number, so it becomes 0x100 or 4. Instead, 0x101 >> 2 remove the 2 least significant bytes, so it becomes 0x1.

To get the 8 least significant bytes of an int you can bitwise-and with 255 (0xFF) then shift them to the left as much as you want and finally bitwise-or with the long number:

int v1 = 0xABAB;
unsigned long v2 = 0;
v2 = v2 | ((v1 & 255) << 5); // change 5 to the number you want
  • Related