各种类型的按位端交换

在各种来源的帮助下,我在我的二进制读取器类中编写了一些SwapBytes方法,它们在ushortuintulong中交换endian,所有这些方法都使用原始C#中的按位操作,而不需要任何unsafe代码。

 public ushort SwapBytes(ushort x) { return (ushort)((ushort)((x & 0xff) <> 8) & 0xff)); } public uint SwapBytes(uint x) { return ((x & 0x000000ff) << 24) + ((x & 0x0000ff00) <> 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; } 

我将如何创建相同的方法,但是对于每种类型的签名版本,例如short,int和long,仅使用与上述相同的方法,以及可以对上述方法进行哪些改进?

而不是在概念上解构为单独的字节,然后以相反的方式重新组合它们,您可以在概念上交换字节组,如下所示:(未经测试)

 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); } 

对32位没有多大帮助(或者根本没有帮助),但对于64位它没有帮助(未测试)

 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); } 

对于签名类型,只需转换为无符号,执行此操作,然后转换回来。

你应该看看以下msdn页面: http : //msdn.microsoft.com/en-us/library/system.bitconverter.aspx

您可以简单地使用Array.Reverse和bitConverter:

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

只需在开头添加一个强制转换为unsigned,然后返回到最后签名。

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

可能需要手动内联对SwapBytes的调用以获得SwapBytes性能。


另外,您可能希望避免交换,而是直接以所需的字节顺序从原始字节数组中读取数据。 有关详细信息,请参阅在C#中读取大端数据的有效方法 。

这可能是替换整数中位的最简单和最懒惰的方法:

 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."); } } } }