2

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.

3

1 Answer 1

2

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:

  1. If you want the bits starting at index 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)).
  2. let 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 
Sign up to request clarification or add additional context in comments.

4 Comments

Thank you for a solution and even more for comments in the code :)
One more question: my NET is older and does not have any Convert.FromHexString. By the way, did you forget to pass one more agument into BitConverter.ToInt32(bytes) (start index) ?
@PanBocian Oh yes you're right. The start index argument would have to be 0 in the call to BitConverter.ToInt32. Indeed Convert.FromHexString() was only introduced with .NET 5 as far as I am aware but there are lots of other questions on that here on StackOverflow :) take a look at this question and use one of the many ways to convert a hex string to bytes :)
An easier alternative to Convert.FromHexString and the BitConverter trickery would be to use Convert.ToInt32("0x34840A00", 16) as @MindSwipe mentioned in the comments. @PanBocian I updated the answer accordingly.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.