Какой порядок байтов, когда BitConverter.IsLittleEndian = false

Я храню числа в формате, эквивалентном их байтам, используя наименьшее возможное количество байтов. В диапазоне от 65535 до 16777215 BitConverter дает мне 4-байтовый массив, но я хочу хранить только 3 байта.

Для приведенного ниже кода мой массив равен [0]254, [1]255, [2]255, [3]0, поэтому я могу вырезать байт [3]. Это на процессоре Core i7. В моем производственном коде перед копированием массива я проверяю BitConverter.IsLittleEndian, чтобы определить, могу ли я отрезать последний байт.

int i = 16777214;
byte[] bytesTemp = BitConverter.GetBytes(i);

byte[] value = null;
if (BitConverter.IsLittleEndian) 
    Array.Copy(bytesTemp, 0, value, 0, 3); 

Мой вопрос: нужно ли мне заботиться о Endian-ness системы, или CLR просто использует этот формат LittleEndian? У меня нет системы BigEndian (и я даже не знаю, как ее получить), чтобы проверить, выходит ли мой массив байтов в обратном порядке.


person winnt93    schedule 25.09.2014    source источник
comment
Это зависит от архитектуры компьютера, большинство архитектур — LittleEndian. Однако код .Net может работать на архитектурах с обратным порядком байтов — .NET Micro Framework может работать на архитектуре с обратным порядком байтов. В версии 4.1 добавлена ​​поддержка обратного порядка байтов.   -  person Donal    schedule 25.09.2014
comment
Надеюсь, вы делаете это не для того, чтобы сэкономить место.   -  person Rawling    schedule 25.09.2014
comment
Если вас беспокоит пространство, вы можете рассмотреть такие вещи, как varint; это занимает 1 байт для 0-127; 2 байта для 128-16 383; 3 байта от 16 384 до 2 097 151; 4 байта от 2 097 152 до 268 435 455; и 5 байтов от 268 435 456 до 4 294 967 295 (при условии, что без знака и т. д.) - и определил порядок следования байтов (/cc @Rawling) (на самом деле, 5 байтов доведут вас до 34 359 738 367 - если вам это действительно нужно)   -  person Marc Gravell    schedule 25.09.2014
comment
@MarcGravell - единственная ссылка на varint, которую я могу найти, это [ссылка] pastebin.com/Qk7LXESQ?   -  person winnt93    schedule 25.09.2014
comment
@ winnt93 это деталь кодирования из буферов протокола; здесь: developers.google.com/protocol-buffers/docs/encoding#varints - в основном, он использует 7-битные данные и 8-й бит в качестве флага продолжения; пример чтения; пример записи   -  person Marc Gravell    schedule 25.09.2014


Ответы (2)


Да, согласно документации , вы должны быть обеспокоены. У них есть пример, когда они меняют местами байты, если архитектура не является желаемой последовательностью байтов.

Что касается того, где взять систему BigEndian, я думаю, что процессоры на базе ARM имеют обратный порядок байтов, хотя я этого не проверял. Поэтому, если вы работаете, например, на устройстве Win RT или телефоне, вы можете получить другое поведение.

person FarmerBob    schedule 25.09.2014
comment
Itaniums тоже имеют обратный порядок байтов, хотя IIRC они могут запускать отдельные процессы с обратным порядком байтов, если это необходимо, и снова IIRC: при запуске .NET они всегда заканчиваются прямым порядком байтов. - person Marc Gravell; 25.09.2014
comment
Это в основном ответило на мой вопрос - да, мне нужно беспокоиться, и я пропустил этот бит в документах MSDN (поэтому теперь у меня есть проверка и array.reverse, когда это необходимо). Однако @MarcGravell сослался на varint, что тоже было полезно. - person winnt93; 25.09.2014

Это полностью зависит от того, что вы делаете с данными. Если вы собираетесь записывать его на диск для переносимого сохранения, тогда да ... Меня, вероятно, волнует порядок следования байтов. Если вы просто собираетесь использовать его для воссоздания int позже в том же процессе (или на той же машине), это, вероятно, не имеет большого значения.

Однако, когда мне действительно нужно беспокоиться о порядке следования байтов, я обычно не добиваюсь этого BitConverter вообще — лично у меня возникло бы искушение использовать маскирование байтов и сдвиг ; тогда вам даже не нужно знать порядок следования байтов — он будет работать одинаково в любой системе. Это также позволяет избежать раздражающе плохого дизайнерского решения BitConverter возвращать массив байтов, а не принимать массив и смещение.

Например:

byte[] buffer = ...

// write little-endian
buffer[offset++] = (byte)(i & 0xFF);
buffer[offset++] = (byte)((i >> 8) & 0xFF);
buffer[offset++] = (byte)((i >> 16) & 0xFF);
buffer[offset++] = (byte)((i >> 24) & 0xFF);
person Marc Gravell    schedule 25.09.2014
comment
Возможно, это немного не по теме, но почему вы говорите, что создавать и возвращать массив, а не принимать его, — это плохое решение? - person Theodoros Chatzigiannakis; 25.09.2014
comment
@TheodorosChatzigiannakis ненужные выделения массива; в большинстве сценариев, где вам нужны байты значения, вы уже работаете с локальными буферами — было бы неплохо иметь возможность использовать: BitConverter.GetBytes(i, buffer, offset); - person Marc Gravell; 25.09.2014
comment
It entirely depends on what you are doing with the data - ну, он пытается удалить лишние 0 байта, поэтому я почти уверен, что он должен заботиться о порядке следования байтов. - person Rawling; 25.09.2014