Does BitConverter handle little-endianness incorrectly?

709 views Asked by At

I'm currently writing something in C#/.NET that involves sending unsigned 16-bit integers in a network packet. The ordering of the bytes needs to be big endian.

At the bit level, my understanding of 'big endian' is that the most significant bit goes at the end, and in reverse for little endian.

And at the byte level, my understanding is the same -- if I'm converting a 16 bit integer to the two 8 bit integers that comprise it, and the architecture is little endian, then I would expect the most significant byte to go at the beginning.

However, BitConverter appears to put the byte with the smallest value at the end of the array, as opposed to the byte with the least-significant value, e.g.

    ushort number = 4;
    var bytes = BitConverter.GetBytes(number);
    Debug.Assert(bytes[BitConverter.IsLittleEndian ? 0 : 1] == 0);

For clarity, if my understanding is correct, then on a little endian machine I would expect the above to return 0x00, 0x04 and on a big endian machine 0x04, 0x00. However, on my little endian Windows x86 workstation running .NET 5, it returns 0x04, 0x00

It's even documented that they've considered the endianness. From: https://learn.microsoft.com/en-us/dotnet/api/system.bitconverter.getbytes?view=net-5.0

The order of bytes in the array returned by the GetBytes method depends on whether the computer architecture is little-endian or big-endian.

Am I being daft or does this seem like the wrong behaviour?

1

There are 1 answers

0
abagonhishead On

I am indeed being daft. As @mjwills pointed out, and Microsoft's documentation explains (https://learn.microsoft.com/en-us/dotnet/api/system.bitconverter.islittleendian?view=net-5.0#remarks):

"Big-endian" means the most significant byte is on the left end of a word. "Little-endian" means the most significant byte is on the right end of a word.

Wikipedia has a slightly better explanation:

A big-endian system stores the most significant byte of a word at the smallest memory address and the least significant byte at the largest. A little-endian system, in contrast, stores the least-significant byte at the smallest address.

So, if you imagine the memory addresses, converting a 16-bit integer with a value of 4 becomes:

Address 0x00 0x01
Little-endian 0x04 0x00
Big-endian 0x00 0x04

Hopefully this'll help anyone equally daft in future!