Reputation: 63
Im asking this question, because couldn't find a solution for this particular case.
I need to extract value (as int or byte) from a hex string and from a given range of bits. For example:
hexString = "0x34840A00"
bits (from calc): 00110100 10000100 00001010 00000000
Now I need bits from 8 to 10: 010
Now convert to int/byte value. Any help? Im struggling with understanding of bit operations here.
Upvotes: 2
Views: 1939
Reputation: 1440
You could first use Convert.FromHexString(hexString)
to get the bytes from your hex string. Then you could either use unsafe pointers or BitConverter.ToInt32()
to convert said bytes to a 32 bit integer to which you can then apply bit shifts and other bit wise operations to extract the bits you need. For example:
string hexString = "0x34840A00";
byte[] bytes = Convert.FromHexString(hexString);
int myInt = BitConverter.ToInt32(bytes, 0);
// myInt looks like this 00110100 10000100 00001010 00000000
// now shift by 8 bits to the right
myInt >>= 8;
// now it looks like this 00000000 00110100 10000100 00001010
// to get the value of the last 3 bits we need to set the first 29 bits to 0
// so we AND them together with 29 0's followed by 3 1's:
myInt &= 0x00000007;
// which results in the following bits:
// 00000000 00000000 00000000 00000010
// leaving you with an integer of the value 010 in binary or 2 in decimal
The bit shifting and AND-ing always follows the same rules:
n
(as counted from the right-most/least significant bit) then shift right by n
bits (in your example n=8
(you don't care about the rightmost 8 bits)).m
be the number of bits you want to keep starting at position n
(in your example you want to keep 3 bits 010
). AND the result together with the integer 2^m - 1
. In your example m=3
this would be 2^3-1 = 8-1 = 7
. Therefore we do myInt &= 0x00000007;
or in short myInt &= 0x7;
.Edit: for older .NET versions and simplifying
string hexString = "0x34840A00";
int myInt = Convert.ToInt32(hexString, 16);
// myInt looks like this 00110100 10000100 00001010 00000000
// now shift by 8 bits to the right
myInt >>= 8;
// now it looks like this 00000000 00110100 10000100 00001010
// to get the value of the last 3 bits we need to set the first 29 bits to 0
// so we AND them together with 29 0's followed by 3 1's:
myInt &= 0x00000007;
// which results in the following bits:
// 00000000 00000000 00000000 00000010
// leaving you with an integer of the value 010 in binary or 2 in decimal
The reusable (and pretty fast) approach would therefore be a method like this:
private static int GetBitsFromHexString(string hexString, int startIndexFromRight, int bitsToKeep)
{
int result = Convert.ToInt32(hexString, 16);
// shift by startIndexFromRight bits to the right
result >>= startIndexFromRight;
// AND the bits together with 32 - bitsToKeep 0's followed by bitsToKeep 1's:
int bitmask = (1 << bitsToKeep) - 1; // is the same as 2^bitsToKeep - 1.
// apply bitmask
result &= bitmask;
return result;
}
Which you would call like this in your example:
int result = GetBitsFromHexString("0x34840A00", 8, 3);
// result is 2 or 010 in binary
Upvotes: 2