【问题标题】:C# little endian or big endian?C# 小端还是大端?
【发布时间】:2010-09-18 02:15:06
【问题描述】:

在允许我们通过 UDP/IP 控制它的硬件文档中, 我找到了以下片段:

在这个通信协议中,DWORD 是一个 4 字节的数据,WORD 是一个 2 字节的数据, BYTE 是单字节数据。存储格式为little endian,即4字节(32bits)数据存储为:d7-d0、d15-d8、d23-d16、d31-d24;双字节(16bits)数据存储为:d7-d0,d15-d8。

我想知道这如何转换为 C#? 我必须在发送之前转换东西吗? 例如,如果我想发送一个 32 位整数,还是一个 4 个字符的字符串?

【问题讨论】:

    标签: c# hardware udp endianness


    【解决方案1】:

    C# 本身并没有定义字节顺序。但是,无论何时转换为字节,您都在做出选择。 BitConverter 类有一个 IsLittleEndian 字段来告诉您它的行为方式,但它没有提供选择。 BinaryReader/BinaryWriter 也是如此。

    我的MiscUtil 库有一个 EndianBitConverter 类,它允许您定义字节序; BinaryReader/Writer 也有类似的等价物。恐怕没有在线使用指南,但它们很琐碎:)

    (EndianBitConverter 还具有普通 BitConverter 中不存在的功能,即在字节数组中就地进行转换。)

    【讨论】:

    • 还记得在 C# 中可以直接复制值,例如*ptr = 值;在这种情况下,您应该关注计算机体系结构的字节顺序。
    • 通过 ReSharper 的反编译,我可以看到我在 Windows PC 上安装的 .Net 框架上 BitConverter 中的 IsLittleEndian 属性只是硬编码返回True,尽管。 .Net 的大端实现有实际案例吗?
    • @Nyerguds:在 .NET Core 中肯定是可行 - 请参阅github.com/dotnet/corefx/blob/master/src/Common/src/CoreLib/…(我不知道我曾经在这样的实现上实际运行过任何东西,但是我绝对会避免假设它永远是真的。)
    • 我认为您的 MiscUtil 库应该重定向到 System.Memory:System.Buffer.Binary.BinaryPrimitives。我相信这些方法将被 JIT 编译器特例化,以使用比 C# 代码更快的硬件指令。
    【解决方案2】:

    你也可以使用

    IPAddress.NetworkToHostOrder(...)
    

    对于short、int或long。

    【讨论】:

    • -1 因为这仅适用于与 Big Endian 的转换,并且 OP 专门要求转换为 Little Endian。特别是,该函数只会在 Little Endian 主机(OP 不需要它)上执行某些操作,并且它会在 Big Endian 主机(OP 需要该功能)上执行nothing。跨度>
    【解决方案3】:

    Re little-endian,简短的回答(我需要做任何事情)是“可能不是,但这取决于你的硬件”。您可以检查:

    bool le = BitConverter.IsLittleEndian;
    

    根据上面所说的,您可能想要反转部分缓冲区。或者,Jon Skeet 有特定的字节序转换器 here(查找 EndianBitConverter)。

    请注意,安腾(例如)是大端的。大多数 Intel 都是 little-endian。

    是特定的 UDP/IP...?

    【讨论】:

    【解决方案4】:

    您需要了解网络字节顺序以及 CPU 字节序。

    通常对于 TCP/UDP 通信,您始终使用 htons 函数(和 ntohs 及其相关函数)将数据转换为网络字节顺序。

    通常网络顺序是大端,但在这种情况下(出于某种原因!)通信是小端,所以这些功能不是很有用。这很重要,因为你不能假设他们实现的 UDP 通信遵循任何其他标准,如果你有一个大端架构,这也会让生活变得困难,因为你不能像你应该的那样用htons 包装所有东西:-(

    但是,如果您来自 intel x86 架构,那么您已经是 little-endian,因此无需转换即可发送数据。

    【讨论】:

      【解决方案5】:

      我正在处理 UDP 多播中的打包数据,我需要一些东西来重新排序 UInt16 八位字节,因为我注意到数据包标头 (Wireshark) 中有错误,所以我做了这个:

          private UInt16 swapOctetsUInt16(UInt16 toSwap)
          {
              Int32 tmp = 0;
              tmp = toSwap >> 8;
              tmp = tmp | ((toSwap & 0xff) << 8);
              return (UInt16) tmp;
          }
      

      在 UInt32 的情况下,

          private UInt32 swapOctetsUInt32(UInt32 toSwap)
          {
              UInt32 tmp = 0;
              tmp = toSwap >> 24;
              tmp = tmp | ((toSwap & 0xff0000) >> 8);
              tmp = tmp | ((toSwap & 0xff00) << 8);
              tmp = tmp | ((toSwap & 0xff) << 24);
              return tmp;
          }
      

      这只是为了测试

          private void testSwap() {
              UInt16 tmp1 = 0x0a0b;
              UInt32 tmp2 = 0x0a0b0c0d;
              SoapHexBinary shb1 = new SoapHexBinary(BitConverter.GetBytes(tmp1));
              SoapHexBinary shb2 = new SoapHexBinary(BitConverter.GetBytes(swapOctetsUInt16(tmp1)));
              Debug.WriteLine("{0}", shb1.ToString());
              Debug.WriteLine("{0}", shb2.ToString());
              SoapHexBinary shb3 = new SoapHexBinary(BitConverter.GetBytes(tmp2));
              SoapHexBinary shb4 = new SoapHexBinary(BitConverter.GetBytes(swapOctetsUInt32(tmp2)));
              Debug.WriteLine("{0}", shb3.ToString());
              Debug.WriteLine("{0}", shb4.ToString());
          }
      

      这是来自哪个输出:

          0B0A: {0}
          0A0B: {0}
          0D0C0B0A: {0}
          0A0B0C0D: {0}
      

      【讨论】:

      • 不错的代码,但有一个错误。 tmp = toSwap >> 24; ==> tmp = (toSwap >> 24) & 0xFF;
      【解决方案6】:

      如果您正在解析并且性能不重要,请考虑以下非常简单的代码:

      private static byte[] NetworkToHostOrder (byte[] array, int offset, int length)
      {
          return array.Skip (offset).Take (length).Reverse ().ToArray ();
      }
      
      int foo = BitConverter.ToInt64 (NetworkToHostOrder (queue, 14, 8), 0);
      

      【讨论】:

        猜你喜欢
        • 2011-07-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-11-03
        • 2010-09-26
        • 2011-05-10
        • 2013-02-27
        • 2011-02-06
        相关资源
        最近更新 更多