Home > C/C++ > Using a single number to contain two other numbers

Using a single number to contain two other numbers

Hi,

Due to a certain restrictive pattern being used at work, I’ve recently had the need to pass along two numbers but only had a single number to do so. It’s a bit of a nasty hack but is my first experience with using bit masking and is a useful technique. The integer being used in the pattern was an unsigned 32 bit integer and the two other integers I wanted to pass along were both unsigned 8 bit integers. The way we figured to send along the two numbers is to basically use half of the 32 bit integer to contain the two 8 bit integers using masking. The process is very simple there are two functions, Encode and Decode. Encode takes in two integers (I’ve made them unsigned 16 bits for the moment but you can easily cast the 8 bit unsigned integer to 16 bit) and returns a 32 bit unsigned int that contains the two. The encode function basically shifts the iFirstNumber into the lower 16 bits of the 32 bit integer. Then iSecondNumber is added to this to give a full 32 bit number.

[code lang="C++"]
uint32 Encode(const uint16 iFirstNumber, const uint16 iSecondNumber)
{
uint32 iEncodedValue((iFirstNumber<< 16) + iSecondNumber);

return iEncodedValue;
}
[/code]

To explain it a little clearer suppose we have iFirstNumber set to 3 (0x00000011) and iSecondNumber set to 1 (0x00000001) we would end up with the encoded value being 0x0000001100000001

You can see that the first 16 bits contain iFirstNumber and the second 16 bits contain the second.

To get the two numbers back out again we have a similar Decode function:

[code lang="C++"]
void Decode(uint32 iValue, uint16& iFirstNumber, uint16& iSecondNumber)
{
iFirstNumber = (uint16)((iValue & 0xFFFF0000) >> 16);
iSecondNumber= (uint16)(iValue & 0x0000FFFF);
}
[/code]

The first number is the overall value ANDed with 0xFFFF0000 and then shifted 16 bits to the right. ANDing the number with 0xFFFF0000 indicates that we are only interested in the first half of the bits in the overall value. It will turn all the rest of the bits in the value to be 0000000000. So after that we will be left with 0×0000001100000000. Now we need to narrow the number down to a 16 bit number. To do this we shift the bits 16 places to the right and cast to a uint16. Casting will remove the proceeding 16 bits(which are all now 0 anyway) and leave us with 0×00000011 which translates to 3.
For iSecondPosition we say that we want only the last half of the bits in the overall value. This leaves us with 0×0000000000000001. Casting this to a uint16 will leave us with 0×00000001 or 1.

In the end we actually didn’t need to do it this way but got it working anyhow. Might be handy for someone maybe!

edlong C/C++

  1. No comments yet.
  1. No trackbacks yet.

Anti-Spam Protection by WP-SpamFree