C# 小端还是大端?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/217980/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 18:34:36  来源:igfitidea点击:

C# little endian or big endian?

c#hardwareudpendianness

提问by TimothyP

In the documentation of hardware that allows us to control it via UDP/IP, I found the following fragment:

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

In this communication protocol, DWORD is a 4 bytes data, WORD is a 2 bytes data, BYTE is a single byte data. The storage format is little endian, namely 4 bytes (32bits) data is stored as: d7-d0, d15-d8, d23-d16, d31-d24; double bytes (16bits) data is stored as: d7-d0 , d15-d8.

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

I am wondering how this translates to C#? Do I have to convert stuff before sending it over? For example, if I want to send over a 32 bit integer, or a 4 character string?

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

采纳答案by Jon Skeet

C# itself doesn't define the endianness. Whenever you convert to bytes, however, you're making a choice. The BitConverterclass has an IsLittleEndianfield to tell you how it will behave, but it doesn't give the choice. The same goes for BinaryReader/BinaryWriter.

C# 本身没有定义字节序。但是,无论何时转换为字节,您都是在做出选择。该BitConverter类有一个IsLittleEndian场告诉你这将如何表现,但它不给的选择。BinaryReader/BinaryWriter 也是如此。

My MiscUtillibrary has an EndianBitConverter class which allows you to define the endianness; there are similar equivalents for BinaryReader/Writer. No online usage guide I'm afraid, but they're trivial :)

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

(EndianBitConverter also has a piece of functionality which isn't present in the normal BitConverter, which is to do conversions in-place in a byte array.)

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

回答by Marc Gravell

Re little-endian, the short answer (to do I need to do anything) is "probably not, but it depends on your hardware". You can check with:

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

bool le = BitConverter.IsLittleEndian;

Depending on what this says, you might want to reverse portions of your buffers. Alternatively, Jon Skeet has specific-endian converters here(look for EndianBitConverter).

根据这句话的意思,您可能想要反转缓冲区的一部分。或者,Jon Skeet在这里有特定的字节序转换器(寻找 EndianBitConverter)。

Note that itaniums (for example) are big-endian. Most Intels are little-endian.

请注意,itanium(例如)是大端的。大多数英特尔都是小端的。

Re the specific UDP/IP...?

重新特定的UDP / IP ...?

回答by gbjbaanb

You need to know about network byte order as well as CPU endian-ness.

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

Typically for TCP/UDP comms, you always convert data to network byte order using the htonsfunction (and ntohs, and their related functions).

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

Normally network order is big-endian, but in this case (for some reason!) the comms is little endian, so those functions are not very useful. This is important as you cannot assume the UDP comms they have implemented follow any other standards, it also makes life difficult if you have a big-endian architecture as you just can't wrap everything with htonsas you should :-(

通常网络顺序是大端,但在这种情况下(出于某种原因!)通信是小端,所以这些功能不是很有用。这很重要,因为您不能假设他们实施的 UDP 通信遵循任何其他标准,如果您拥有大端架构,这也会使生活变得困难,因为您无法htons按照应有的方式包装所有内容:-(

However, if you're coming from an intel x86 architecture, then you're already little-endian, so just send the data without conversion.

但是,如果您来自 intel x86 架构,那么您已经是小端,因此只需发送数据而不进行转换。

回答by Jan Bannister

You can also use

你也可以使用

IPAddress.NetworkToHostOrder(...)

For short, int or long.

简而言之,int 或 long。

回答by mafu

If you're parsing and performance is not critical, consider this very simple code:

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

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

回答by Marko Samiri?

I'm playing around with packed data in UDP Multicast and I needed something to reorder UInt16 octets since I noticed an error in packet header (Wireshark), so I made this:

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

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

In case of UInt32,

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

This is just for testing

这只是为了测试

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

from which output was this:

从哪个输出是这样的:

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