Deep C# - Bit Manipulation
Written by Mike James   
Monday, 28 July 2025
Article Index
Deep C# - Bit Manipulation
Basic operations
BitConverter

BitConverter

One of the most common reasons for having to resort to bit manipulation is that you have a raw stream of bytes and need to turn them into structured data.

As the logical operations don’t work for non-integral types this is something of a problem if you want to convert bytes into floats, say. It is even not particularly easy to convert bytes into integral types.

That is the problem that you most often have to solve is that you have a stream of bytes and groups of bytes represent either floating point or integer values and you need to convert the stream into those types. 

This is where the BitConverter class becomes important. It is intended to help you serialise an object to bytes and back again but this doesn’t stop us using it for other purposes.

The BitConverter has a GetBytes method that will convert any of the standard data type into a byte array and a specific ToType method that converts the same byte array back into the appropriate data type. So for example

double a=1.234;
byte[] data;
data=BitConverter.GetBytes(a);

returns an eight-byte array containing the bits that were stored in the eight-byte double.

To reconstruct the double we use:

double b = BitConverter.ToDouble(data);

There are also two alternative forms of the ToType method that let you specify the location in the array of the data – very useful when processing raw byte streams.

The BitConverter class allows you to both generate and reconstruct data from byte streams but it also gives you the opportunity to perform logical operations on a range of data types as a byte array and then restore the result.

It is important to realise that BitConverter is “little endian” which is something that non-Intel programmers don’t take for granted.

For example, what value is stored in x after this:

byte[] IntVal={0x00,0x01} ;
Int16 x = BitConverter.ToInt16(IntVal, 0);

If you think the answer is 1 then you are working in big endian format, i.e. the high order byte comes first, but the actual answer on Intel-based machines is 256 because they are little endian and take the first byte as the low order byte.

Usually this isn’t a problem once you know about it, but it can result in some messy byte switching if you are trying to work with little endian data.

csharp

String Problems

There is one other problem with using BitConverter and strings.

What do you think is stored in s in this case?

byte[] data={(byte)'A',(byte)'B',(byte)'C'};
String s = BitConverter.ToString(data);

You might think that it would be “ABC” but the answer is “41-53-4A”, i.e. a string representation of the hexadecimal values stored in the byte array.

In short, BitConverter isn’t much use converting raw bytes into strings. The only solution to this problem seems to be to use one of the “unsafe” string constructors that takes a pointer to a byte array.

unsafe String ToString(sbyte[] data){
 string s;
 fixed(sbyte* pdata=data) {
  s = new string(pdata) ;
 }
 return s;
}

To use this method you have to compile with “allow unsafe”.

If you now try:

sbyte[] data ={(sbyte)'A',(sbyte)'B',(sbyte)'C',0 };
string s = ToString(data);

you will see that the string “ABC” has been constructed from the raw byte array.

There is a lot more to say about bit manipulation in C#, there’s a bit array type for example, but this will have to wait.

Postlude

Bit manipulation is something we try to avoid, but in some applications it is unavoidable due to the need to interact with raw data, or even raw hardware. In most cases you can do the job with safe code, but you still need to understand binary representation and all of the techniques involved in working with it. Occasionally you will still need to resort to unsafe code, but with care this can be made effectively safe.

Related Articles

Binary Arithmetic       

Hexadecimal       

Binary - Negative Numbers       

JavaScript Bit Manipulation     

SNTP time class       

The Mod function     

Deep C#

 Buy Now From Amazon

DeepCsharp360

 Chapter List

  1. Why C#?
    I Strong Typing & Type Safety
  2. Strong Typing
       Extract 
    Why Strong Typing
  3. Value & Reference
  4.    Extract Value And Reference
  5. Structs & Classes
       Extract
    Structs & Classes 
  6. Inheritance
      
    Extract
    Inheritance
  7. Interfaces & Multiple Inheritance
      
    Extract Interface
  8. Controlling Inheritance
    II Casting & Generics
  9. Casting - The Escape From Strong Typing
      
    Extract Casting I
  10. Generics
  11. Advanced Generics
  12. Anonymous & Dynamic
    Typing
    III Functions
  13. Delegates 
  14. Multicast Delegates
  15. Anonymous Methods, Lambdas & Closures
    IV Async
  16. Threading, Tasks & Locking
  17. The Invoke Pattern
  18. Async Await
  19. The Parallel For
    V Data - LINQ, XML & Regular Expressions
  20. The LINQ Principle
  21. XML
  22. LINQ To XML
  23. Regular Expressions
    VI Unsafe & Interop
  24. Interop
  25. COM
  26. Custom Attributes
  27. Bit Manipulation ***NEW!
  28. Advanced Structs
  29. Pointers 

Extra Material

 <ASIN:1871962714>

 <ASIN:B09FTLPTP9>

To be informed about new articles on I Programmer, sign up for our weekly newsletter, subscribe to the RSS feed and follow us on Twitter, Facebook or Linkedin.

Banner


Langfuse Goes Truly Open Source
04/08/2025

The news is that Langfuse, the LLM observability platform,
has made all it commercial product features available for free and open source. But first of all, what is Langfuse?



NIST Finalizes ‘Lightweight Cryptography’ Standard to Protect Small Devices
20/08/2025

The problem of security on small devices is a serious one so it is a good job we have the NIST on the case. Its latest effort is to point us in the direction of a new set of cryptographic functions wh [ ... ]


More News

pico book

 

Comments




or email your comment to: comments@i-programmer.info

 



Last Updated ( Monday, 28 July 2025 )