Bit matching for different types

Using various sources, I wrote several SwapBytes methods in my class of binary readers that change the final element in ushort , uint and ulong , all use bitwise operations in the original C #, without any unsafe code needed.

 public ushort SwapBytes(ushort x) { return (ushort)((ushort)((x & 0xff) << 8) | ((x >> 8) & 0xff)); } public uint SwapBytes(uint x) { return ((x & 0x000000ff) << 24) + ((x & 0x0000ff00) << 8) + ((x & 0x00ff0000) >> 8) + ((x & 0xff000000) >> 24); } public ulong SwapBytes(ulong value) { ulong uvalue = value; ulong swapped = ((0x00000000000000FF) & (uvalue >> 56) | (0x000000000000FF00) & (uvalue >> 40) | (0x0000000000FF0000) & (uvalue >> 24) | (0x00000000FF000000) & (uvalue >> 8) | (0x000000FF00000000) & (uvalue << 8) | (0x0000FF0000000000) & (uvalue << 24) | (0x00FF000000000000) & (uvalue << 40) | (0xFF00000000000000) & (uvalue << 56)); return swapped; } 

How can I start creating the same methods, but for signed versions of each of these types, for example short, int and long, using only the same methods as above, and what improvements can be made to the methods above?

+5
source share
4 answers

Instead of conceptually deconstructing individual bytes and then reassembling them, you can conceptually change the byte groups as follows: (not tested)

 public uint SwapBytes(uint x) { // swap adjacent 16-bit blocks x = (x >> 16) | (x << 16); // swap adjacent 8-bit blocks return ((x & 0xFF00FF00) >> 8) | ((x & 0x00FF00FF) << 8); } 

It does not help much (or at all) for 32 bits, but for 64 bits it does (is not tested)

 public ulong SwapBytes(ulong x) { // swap adjacent 32-bit blocks x = (x >> 32) | (x << 32); // swap adjacent 16-bit blocks x = ((x & 0xFFFF0000FFFF0000) >> 16) | ((x & 0x0000FFFF0000FFFF) << 16); // swap adjacent 8-bit blocks return ((x & 0xFF00FF00FF00FF00) >> 8) | ((x & 0x00FF00FF00FF00FF) << 8); } 

For signed types simply cast to unsigned, do this, then discard.

+14
source

You should take a look at the following msdn page: http://msdn.microsoft.com/en-us/library/system.bitconverter.aspx

You can simply use Array.Reverse and bitConverter:

  int value = 12345678; byte[] bytes = BitConverter.GetBytes(value); Array.Reverse(bytes); int result = BitConverter.ToInt32(bytes, 0); 
+7
source

Just add the unsigned cast at the beginning and back to the signed one at the end.

 public long SwapBytes(long value) { return (long)SwapBytes((ulong)value); } 

You may need to manually enable the SwapBytes call for maximum performance.


In another note, you may need to avoid sharing, in favor of directly reading data from the original byte array in the desired instantiation. See Efficient way to read large endian data in C # for details.

+2
source

This is perhaps the easiest and laziest way to replace bits with an integer:

 using System; namespace BitSwap { class Program { static void Main() { //swaps bits {p, p+1, …, p+k-1} with bits {q, q+1, …, q+k-1} of n. Console.WriteLine("n="); uint n = uint.Parse(Console.ReadLine()); Console.WriteLine("p="); int p = int.Parse(Console.ReadLine()); Console.WriteLine("q="); int q = int.Parse(Console.ReadLine()); Console.WriteLine("k="); int k = int.Parse(Console.ReadLine()); int i; int s; if ((p + k - 1) < 32 && (q + k - 1) < 32 && p > 0 && q > 0) // for integer { for (i = p, s = q; i <= p + k - 1 && s <= q + k - 1; i++, s++) { uint firstBits = (n >> i) & 1; uint secondBits = (n >> s) & 1; uint maskFirstBits = (uint)1 << i; uint maskSecondBits = (uint)1 << s; n = (n & ~maskFirstBits) | (secondBits << i); n = (n & ~maskSecondBits) | (firstBits << s); } Console.WriteLine("Result: {0}", n); } else { Console.WriteLine("Invalid entry."); } } } } 
-1
source

Source: https://habr.com/ru/post/1273717/


All Articles