【问题标题】:Why do I get the following output when inverting bits in a byte?为什么在字节中反转位时会得到以下输出?
【发布时间】:2025-12-31 23:20:04
【问题描述】:

假设:

转换一个 byte[] 从小端到大 Endian 意味着反转位的顺序 byte[] 的每个字节。

假设这是正确的,我尝试了以下方法来理解这一点:

byte[] data = new byte[] { 1, 2, 3, 4, 5, 15, 24 };
byte[] inverted = ToBig(data);

var little = new BitArray(data);
var big = new BitArray(inverted);

int i = 1;

foreach (bool b in little)
{
    Console.Write(b ? "1" : "0");
    if (i == 8)
    {
        i = 0;
        Console.Write(" ");
    }
    i++;
}

Console.WriteLine();

i = 1;

foreach (bool b in big)
{
    Console.Write(b ? "1" : "0");
    if (i == 8)
    {
        i = 0;
        Console.Write(" ");
    }
    i++;
}

Console.WriteLine();

Console.WriteLine(BitConverter.ToString(data));
Console.WriteLine(BitConverter.ToString(ToBig(data)));

foreach (byte b in data)
{
    Console.Write("{0} ", b);
}

Console.WriteLine();

foreach (byte b in inverted)
{
    Console.Write("{0} ", b);
}

转换方法:

private static byte[] ToBig(byte[] data)
{
    byte[] inverted = new byte[data.Length];

    for (int i = 0; i < data.Length; i++)
    {
        var bits = new BitArray(new byte[] { data[i] });
        var invertedBits = new BitArray(bits.Count);

        int x = 0;

        for (int p = bits.Count - 1; p >= 0; p--)
        {
            invertedBits[x] = bits[p];
            x++;
        }

        invertedBits.CopyTo(inverted, i);
    }

    return inverted;
}

这个小应用程序的输出与我的预期不同:

00000001 00000010 00000011 00000100 00000101 00001111 00011000

00000001 00000010 00000011 00000100 00000101 00001111 00011000 

80-40-C0-20-A0-F0-18

01-02-03-04-05-0F-18

1 2 3 4 5 15 24 

1 2 3 4 5 15 24 

由于某种原因,数据保持不变,除非使用 BitConverter 打印。

我不明白什么?

更新

新代码产生以下输出:

10000000 01000000 11000000 00100000 10100000 11110000 00011000 

00000001 00000010 00000011 00000100 00000101 00001111 00011000 

01-02-03-04-05-0F-18

80-40-C0-20-A0-F0-18

1 2 3 4 5 15 24 

128 64 192 32 160 240 24 

但是正如我现在被告知的那样,无论如何我的方法都不正确,因为我应该反转字节 而不是位?

与我合作的这位硬件开发人员告诉我反转位,因为他无法读取数据。

我使用它的上下文

将使用它的应用程序并不能真正使用数字。

我应该将比特流保存到文件中

1 = 白色,0 = 黑色。

它们代表 256x64 位图的像素。

byte 0 到 byte 31 代表第一行像素 byte 32 到 byte 63 第二行像素。

我有输出这些位的代码...但开发人员告诉 我他们的顺序错误......他说字节很好,但位不是。

所以我很困惑:p

【问题讨论】:

  • 仅供参考,字节序是指单词中字节的顺序,而不是字节中的位。

标签: c# .net endianness


【解决方案1】:

没有。字节序是指字节的顺序,而不是位。大端系统首先存储最重要的字节,而小端系统首先存储最不重要的字节。一个字节中的位保持相同的顺序。

您的 ToBig() 函数似乎返回的是原始数据而不是位交换数据。

【讨论】:

    【解决方案2】:

    我看到的一个大问题是 ToBig 更改了传递给它的 data[] 数组的内容。

    您在名为 data 的数组上调用 ToBig,然后将结果分配给 inverted,但由于您没有在 ToBig 中创建新数组,因此您修改了两个数组,然后继续处理数组datainverted 是不同的,但实际上并非如此。

    【讨论】:

      【解决方案3】:

      此时您的方法可能是正确的。字节序有不同的含义,取决于硬件。

      通常,它用于在计算平台之间进行转换。大多数 CPU 供应商(现在)对不同的芯片组使用相同的位顺序,但不同的字节顺序。这意味着,如果您将一个 2 字节的 int 从一个系统传递到另一个系统,则无需处理这些位,而是交换字节 1 和 2,即:

      int somenumber -> byte[2]: somenumber[high],somenumber[low] ->  
      byte[2]: somenumber[low],somenumber[high] -> int newNumber
      

      但是,这并不总是正确的。一些硬件仍然使用倒置的 BIT 排序,所以你所拥有的可能是正确的。您需要信任您的硬件开发人员。或进一步调查。

      我建议在 Wikipedia 上阅读此内容 - 总是一个很好的信息来源:

      http://en.wikipedia.org/wiki/Endianness


      您的 ToBig 方法存在错误。

      最后:

       invertedBits.CopyTo(data, i);
      }
      
      return data;
      

      您需要将其更改为:

      byte[] newData = new byte[data.Length];
      invertedBits.CopyTo(newData, i);
      }
      return newData;
      

      您正在重置输入数据,因此您接收到的两个数组都被反转了。问题是数组是引用类型,所以可以修改原始数据。

      【讨论】:

      • 好的,这样效果更好,但我做错了因为我必须反转字节而不是位?
      • 没错。字节顺序需要切换,位顺序保持不变。
      • 我刚刚对其进行了测试 - 您当前的代码有效(第一次和第三次打印),但有一个例外: ToString() 方法没有给出您的期望,因为它们正在转换字节 []将自身而不是数组的内容引用到字符串。
      • James - 对与错 - 只有当硬件与他正在使用的 CPU 具有相同的位顺序时,您的假设才成立。我不确定他使用的是什么硬件,但有时您需要交换位,而不仅仅是字节。
      • Reedcopsey,你可能是完全正确的。硬件正在中国开发,我不知道他们使用的是什么 CPU。和开发者沟通很困难,但我想你可能已经澄清了一些事情!!!
      【解决方案4】:

      正如 grayfade 已经说过的,字节顺序与位顺序无关。

      您的代码未按预期执行的原因是 ToBig 方法更改了您发送给它的数组。这意味着在调用该方法后,数组被反转,datainverted 只是指向同一个数组的两个引用。

      这是该方法的更正版本。

      private static byte[] ToBig(byte[] data) {
         byte[] result = new byte[data.length];
         for (int i = 0; i < data.Length; i++) {
            var bits = new BitArray(new byte[] { data[i] });
            var invertedBits = new BitArray(bits.Count);
            int x = 0;
            for (int p = bits.Count - 1; p >= 0; p--) {
               invertedBits[x] = bits[p];
               x++;
            }
            invertedBits.CopyTo(result, i);
         }
         return result;
      }
      

      编辑:
      这是一个改变字节数组字节序的方法:

      static byte[] ConvertEndianness(byte[] data, int wordSize) {
          if (data.Length % wordSize != 0) throw new ArgumentException("The data length does not divide into an even number of words.");
          byte[] result = new byte[data.Length];
          int offset = wordSize - 1;
          for (int i = 0; i < data.Length; i++) {
              result[i + offset] = data[i];
              offset -= 2;
              if (offset < -wordSize) {
                  offset += wordSize * 2;
              }
          }
          return result;
      }
      

      例子:

      byte[] data = { 1,2,3,4,5,6 };
      byte[] inverted = ConvertEndianness(data, 2);
      Console.WriteLine(BitConverter.ToString(inverted));
      

      输出:

      02-01-04-03-06-05
      

      第二个参数是字长。由于字节序是单词中字节的顺序,因此您必须指定单词的大小。

      编辑 2:
      这是一种更有效的位反转方法:

      static byte[] ReverseBits(byte[] data) {
          byte[] result = new byte[data.Length];
          for (int i = 0; i < data.Length; i++) {
              int b = data[i];
              int r = 0;
              for (int j = 0; j < 8; j++) {
                  r <<= 1;
                  r |= b & 1;
                  b >>= 1;
              }
              result[i] = (byte)r;
          }
          return result;
      }
      

      【讨论】:

        最近更新 更多