字节和位数组中的C#位顺序

字节和位数组中的C#位顺序,c#,byte,bit,endianness,C#,Byte,Bit,Endianness,我正试着让我的头脑去理解endianess和bit ordering 编辑:正如评论中所指出的,endianess与我的问题无关,但我想把它放在这里只是为了完整。至少没有人反驳我的“定义” 到目前为止我所学到的:如果一个值(可能是一个字)由多个字节(字:2个字节)组成,则有两种不同的方法将该值保存在连续的内存块中。假设我们有一个十进制43210的值(0xA8CA,1010100011001010) BigEndian(第一个)保存字节,这将对较低地址的值大小产生更大的影响,有点像我们写的普通阿

我正试着让我的头脑去理解endianess和bit ordering

编辑:正如评论中所指出的,endianess与我的问题无关,但我想把它放在这里只是为了完整。至少没有人反驳我的“定义”

到目前为止我所学到的:如果一个值(可能是一个字)由多个字节(字:2个字节)组成,则有两种不同的方法将该值保存在连续的内存块中。假设我们有一个十进制43210的值(0xA8CA,1010100011001010)

  • BigEndian(第一个)保存字节,这将对较低地址的值大小产生更大的影响,有点像我们写的普通阿拉伯数字

    Memory address |  1000  |  1001  
    ---------------|--------|---------
    Bytes          |   A8   |   CA
    
    Memory address |  1000                         |  1001  
    Bit values     |128|64 |32 |16 |8  |4  |2  |1  |128|64 |32 |16 |8  |4  |2  |1  |
    --------------------------------------------------------------------------------
    Bits           | 1   0   1   0   1   0   0   0 | 1   1   0   0   1   0   1   0
    
  • LittleEndian(第一个)保存对较低地址的值大小影响较小的字节

    Memory address |  1000  |  1001  
    ---------------|--------|---------
    Bytes          |   CA   |   A8
    
这是正确的吗

我学到的第二件事是,有两种不同的方法在内存中保存一个字节的位(坚持使用43210和BigEndian):

  • 最高有效位(first/left)保存字节的analoguos BigEndian,在写入阿拉伯数字时,对内存中的值大小影响最大的位

    Memory address |  1000  |  1001  
    ---------------|--------|---------
    Bytes          |   A8   |   CA
    
    Memory address |  1000                         |  1001  
    Bit values     |128|64 |32 |16 |8  |4  |2  |1  |128|64 |32 |16 |8  |4  |2  |1  |
    --------------------------------------------------------------------------------
    Bits           | 1   0   1   0   1   0   0   0 | 1   1   0   0   1   0   1   0
    
  • 最低有效位(first/left)反转字节内的位顺序,因此区分偶数和非偶数的位首先出现

    Memory address |  1000                         |  1001  
    Bit values     |1  |2  |4  |8  |16 |32 |64 |128|1  |2  |4  |8  |16 |32 |64 |128|
    --------------------------------------------------------------------------------
    Bits           | 0   0   0   1   0   1   0   1 | 0   1   0   1   0   0   1   1   
    
这也对吗

我的情况和问题来了:我正在通过网络接收数据。协议(Modbus)规定a)数据传输为BigEndian,当必须返回位时,以字节为单位,MSB位于左侧,LSB位于右侧。我正在用C#,.NET4.5编程

在很多情况下,我使用BitConverter类检查我的系统(
BitConverter.IsLittleEndian
)的Endiance,以便通过NetSocket正确传递单词值

    public static byte[] CorrectEndianess(byte[] in_byteArray)
    {
        if (BitConverter.IsLittleEndian)
            return in_byteArray.Reverse().ToArray();
        else return in_byteArray;
    }
当我接收到一个字节,其中包含代表八个线圈(或输入)状态的八位时,它就会停止运行。根据定义,Modbus协议提供以下内容(示例):

包含此信息的
字节
在调试器中显示为值“1”,这很好。但是,我需要将每一位作为布尔值。C#提供了
位数组
,一个我可以传递字节的类,它返回一个
bool[]
,非常适合我的用途

    BitArray ba = new BitArray(new byte[1] { my_byte_which_is_of_value_1 });
如果我打印位数组,
ba[0]
包含值
true
,其余值
false
。所以我认为BitArray认为一个字节首先是LSB。这很奇怪,因为它会中断位的剩余处理,而位的剩余处理(例如)
ba[7]
预期为
true

长话短说,我的主要问题是:

我如何检查在
位数组
字节
中采用的位顺序,以便始终知道我的LSB和MSB在哪里?


旁注:从右到左的表示语言中的数字是用BigEndian-right写的吗?

您是否尝试过在发送数据的主机上使用IPAddress.HostToNetworkOrder,然后在接收端使用IPAddress.NetworkToHostOrder,而不是确定远程系统的端号?这样,您就可以使代码不受endianneas的影响


现在,在几句评论之后,我得到了我想要的答案。如果我仔细看的话,我自己也会被它绊倒的


正如@Alex Farber所指出的,MSDN声明LSB在位数组中具有最低的索引。我在这里也找到了这个答案:

Endianness不影响单字节内的位顺序。BitArray根据其定义工作:
每个字节的最低有效位表示最低索引值:“bytes[0]&1”表示位0,“bytes[0]&2”表示位1,“bytes[0]&4”表示位2,依此类推。
因此,看起来您试图处理endianness,试图从Modbus中读取单个字节有点过头了。只需按原样使用这些字节,除非协议发送字或双字。我应该仔细看看。因此:
ba[0]
始终是LSB吗?你的第二条评论:好吧,如果我只返回一个字节的数据(这是一个有效的用例),并且必须访问这一字节的位,我不会将其视为过度使用。我的意思是:当你读取一个字节时,endianness是不相关的。只有当你读取单词、双单词和更大的数字时,你才需要考虑endianness。同样,单个字节内的位顺序不受影响(除非通信协议使用反向位顺序,这应在文档中提及)。要访问位,您可以使用位数组或位操作-这是您的选择。好的,所以我有整个“Endian”部分,只是为了完整性,因为这两个部分有4种组合。你是对的,endianess不是单字节问题的一部分。我不需要确定远程系统的endianess,我知道它想要什么endianess,它返回什么。另外,您提供的函数还值得记住,但由于我想从一个字节中以正确的顺序读取单个位,因此它们在这里没有任何用处,因为它们只适用于int。(字到长)