C# 以小尾数方式从整数到字节的数组(通用函数)

C# 以小尾数方式从整数到字节的数组(通用函数),c#,C#,我有这个方法可以将长字节数组转换成小字节数组 public static byte[] UnsignedIntegerToLEByteArray(ulong value) { // Value in bytes... in your system's endianness (let's say: little endian) byte[] bytes = BitConverter.GetBytes(value); // If it was big endian,

我有这个方法可以将长字节数组转换成小字节数组

public static byte[] UnsignedIntegerToLEByteArray(ulong value)
{    
    // Value in bytes... in your system's endianness (let's say: little endian)
    byte[] bytes = BitConverter.GetBytes(value);

    // If it was big endian, reverse it
    if (!BitConverter.IsLittleEndian)
        Array.Reverse(bytes); 

    return bytes;
}
我的目标是也将其用于短数据类型,如int、short等。请参见此处:

byte a = 0xAA;
ushort b = 0xEEAA;
uint c = 0xAABBCCDD;
ulong d = 0xAABBCCDDAAAAAABB;
// If you passed short below, you are only interested
// in first two bytes of the array
byte []tmp = DppUtilities.UnsignedIntegerToLEByteArray(b);
如果我的机器是little endian,这就行了。
如果在big endian机器上运行,它也会工作吗?我想是的,但我想验证一下。

我有同样的东西,我测试了它

我可以告诉你它100%有效。例如,如果你想亲自查看,你可以假装你需要它。因此,可以反转字节数组,如果它是
IsLittleEndian
,则反转它


在方法中,您的输出始终是
LittleEndian
,这正是您想要的。

位转换器类似。GetBytes
具有不同的重载,您应该以相同的方式执行:

public static byte[] UnsignedIntegerToLEByteArray(ulong value) { ...
public static byte[] UnsignedIntegerToLEByteArray(int value) { ...
public static byte[] UnsignedIntegerToLEByteArray(short value) { ...
编译器在使用重载时会选择正确的重载,就像您之前所做的那样:

byte []tmp = DppUtilities.UnsignedIntegerToLEByteArray(b);

如果使用一个方法尝试检查零字节,则会产生错误的结果: 如何判断数字
00 00 12 34
应该反转2个字节还是4个字节?

您可以在
IntPtr
Marshal
的帮助下玩一个小把戏,以便转换任何结构(包括
byte
ushort
ulong
):

编辑:问题中的实现有什么问题?(摘自评论)。 或者,重申这个问题,
IntPtr
Marshal
的内容是什么

问题实施的主要问题是初始转换为
ulong

// Disclaimer: the structure will be reversed as a whole, not field by field
public static byte[] ToLEByteArray<T>(T value) where T: struct {
  int size = Marshal.SizeOf(typeof(T));
  byte[] bytes = new byte[size];

  IntPtr p = Marshal.AllocHGlobal(size);

  try {
    Marshal.StructureToPtr(value, p, true);
    Marshal.Copy(p, bytes, 0, size);
  }
  finally {
    Marshal.FreeHGlobal(p);
  }

  // If it was big endian, reverse it
  if (!BitConverter.IsLittleEndian)
    Array.Reverse(bytes);

  return bytes;
}
  // all the arguments will be converted to ulong 
  public static byte[] UnsignedIntegerToLEByteArray(ulong value)
为了说明这个问题,想象一下,我们有两个值

Byte  x = 0x12;               // 18
ulong u = 0x0000000000000012; // 18
预期产量为

new byte[] {0x12};                      // for a single byte
new byte[] {0x12, 0, 0, 0, 0, 0, 0, 0}; // for 8 bytes, i.e. ulong 
然而,实际输出将是

new byte[] {0x12, 0, 0, 0, 0, 0, 0, 0};
对于
byte
ulong
。如果您想将数值(
byte
short
ulong
等)写入二进制文件,并将其传递到二进制流等,这种错误行为可能会导致问题:

使用(Stream stm=…){
...
字节[]缓冲区=无符号整数字节数组(…);

stm.Write(buffer,offset,buffer.Length);//如果你有一些包含多个字段的
struct
,你不是必须反转每个字段而不是整个
struct
吗?@PetSerAl:它将整个结构反转;因此在你当前的实现中,实现对任意
struct
@quser:不是很有用(这是个问题)您将其转换为
ulong
,因此,如果实际参数是
Byte
,它将被视为
ulong
,您将得到8项数组而不是1项数组是的,但这对我来说不是问题,那么我将只读取数组后面的第一个字节(我知道我首先向它传递了一个字节,对吗?)。还有其他问题吗?@quser:从技术上讲,您可以为
字节
获取数组的第一项,或者说,为
uint
获取数组的前4项,但这是一个容易出错的实现:您必须为方法的每次调用执行一个调用后过程。“如果您尝试使用单个方法检查零字节,则会产生错误的结果:如何判断数字00 00 12 34是否应反转2或4字节?“你能解释一下你在这里的意思吗?我用多种可能性测试了我的函数,它可以工作。如果我理解正确,你只有一个方法,你可以通过所有不同的类型(int,short,…)对于使用隐式强制转换的方法。该方法如何知道它必须反转多少字节?它将强制转换uint到ulong reverse long,并返回数组,请尝试将低值(例如1)传递给该方法。那么它将如何解释1为long,以小端方式从中获取字节数组,并返回结果。不是吗?
new byte[] {0x12};                      // for a single byte
new byte[] {0x12, 0, 0, 0, 0, 0, 0, 0}; // for 8 bytes, i.e. ulong 
new byte[] {0x12, 0, 0, 0, 0, 0, 0, 0};
  using (Stream stm = ...) {
    ...
    Byte[] buffer = UnsignedIntegerToLEByteArray(...);

    stm.Write(buffer, offset, buffer.Length); // <- the (possibly!) erroneous write
    ...
  }