Small integer to byte array (common function)

I have this method for converting a long to a small array of endian bytes

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

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

    return bytes;
}

My goal is to use it for short data types like int, short etc. See here:

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

It works if my car is a little oriented. Will it work if it is running on a large machine? I think so, but I would like to confirm.

+4
source share
3 answers

You can play the trick with IntPtrand Marshalto transform any structure (including byte, ushortand 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;
}

....

  Byte b = 123;
  ushort s = 123;
  ulong l = 123;

  Byte[] result_byte = ToLEByteArray(b);
  Byte[] result_ushort = ToLEByteArray(s);
  Byte[] result_ulong = ToLEByteArray(l);

....

  int i = 123456; 
  Byte[] result_int = ToLEByteArray(i);

EDIT : what's wrong with the implementation in question? (from the comment). Or, asking the question, what are these things with IntPtr, Marshalfor?

ulong:

  // 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 ..), , ..:

  using (Stream stm = ...) {
    ...
    Byte[] buffer = UnsignedIntegerToLEByteArray(...);

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

, .

, 100%. , , , , . , , IsLittleEndian.

LittleEndian , .

0

Similarly BitConverter.GetBytes, there are different overloads for this, you should do it like this:

public static byte[] UnsignedIntegerToLEByteArray(ulong value) { ...
public static byte[] UnsignedIntegerToLEByteArray(int value) { ...
public static byte[] UnsignedIntegerToLEByteArray(short value) { ...

The compiler selects the correct overload when using it, as you already did:

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

If you try to do this with one method that tries to check for null bytes, this will lead to incorrect results: How to determine if a number should 00 00 12 34cancel 2 or 4 bytes?

0
source

Source: https://habr.com/ru/post/1611395/


All Articles