Мне нужно преобразовать int
в byte[]
один из способов сделать это заключается в использовании BitConverter.GetBytes()
. Но я не уверен, что это соответствует следующей спецификации:
Целое число со знаком XDR - это 32-разрядное значение, которое кодирует целое число в диапазоне [-2147483648,2147483647]. Целое число представлено в двух дополнительных обозначениях. Самые старшие и младшие байты равны 0 и 3 соответственно. Целые числа объявляются следующим образом:
Источник: RFC1014 3.2
Как я могу сделать преобразование int в байты, которое удовлетворяло бы вышеупомянутой спецификации?
c#
.net
bit-manipulation
nfs
Питер
источник
источник
Ответы:
RFC просто пытается сказать, что целое число со знаком является нормальным 4-байтовым целым числом с байтами, упорядоченными в порядке с прямым порядком байтов.
Теперь вы, скорее всего, работаете на машине с прямым порядком байтов и
BitConverter.GetBytes()
дадите вамbyte[]
обратное. Так что вы можете попробовать:Однако, чтобы код был максимально переносимым, вы можете сделать это следующим образом:
источник
byte[] result = intBytes;
?intBytes
уже не тот массив, который вы хотите?result
избыточно в этом фрагменте кода. Тем не менее, я чувствовал, что было более педагогично явно показать читателям, каков был результат, чем предполагать, что они могут понять, что результат содержится в некоторой переменной с именемintBytes
. Кроме того, выполнение присваивания является дешевым, поскольку оно не копирует и не выделяет новую память, а просто добавляет новое имя к уже выделенному массиву. Так почему бы не сделать это?Вот еще один способ сделать это: как мы все знаем, 1x байт = 8x бит, а также «обычное» целое число (int32) содержит 32 бита (4 байта). Мы можем использовать оператор >>, чтобы сдвинуть биты вправо (оператор >> не меняет значение.)
источник
& 0xFF
биты не нужны.unchecked
блок. В настоящее время это работает, только если целочисленная проверка переполнения отключена в настройках компилятора.BitConverter.GetBytes(int)
почти делает то, что вы хотите, за исключением того, что порядок байтов не так.Вы можете использовать метод IPAddress.HostToNetwork, чтобы поменять байты внутри целочисленного значения перед использованием
BitConverter.GetBytes
или использованием класса EndianBitConverter Джона Скита . Оба метода делают правильные вещи (тм) в отношении переносимости.источник
Когда я смотрю на это описание, у меня возникает ощущение, что это целое число xdr является просто «стандартным» целым числом с прямым порядком байтов, но оно выражено самым запутанным образом. Обозначение дополнения Two лучше известно как U2, и это то, что мы используем на современных процессорах. Порядок байтов указывает, что это запись с прямым порядком байтов .
Итак, отвечая на ваш вопрос, вы должны инвертировать элементы в вашем массиве (0 <-> 3, 1 <-> 2), так как они закодированы в порядке с прямым порядком байтов. Просто чтобы убедиться, вы должны сначала проверить,
BitConverter.IsLittleEndian
на какой машине вы работаете.источник
Почему весь этот код в примерах выше ...
Структура с явным макетом действует в обоих направлениях и не имеет никакого снижения производительности.
Обновление: так как есть вопрос о том, как бороться с порядком байтов, я добавил интерфейс, который иллюстрирует, как это абстрагировать. Другая реализующая структура может иметь дело с противоположным случаем
источник
Если вы хотите получить более общую информацию о различных способах представления чисел, в том числе о дополнении Two, посмотрите:
Два дополнения и подписи числовых представлений в Википедии
источник
Другой способ заключается в использовании BinaryPrimitives, как так
byte[] intBytes = BitConverter.GetBytes(123); int actual = BinaryPrimitives.ReadInt32LittleEndian(intBytes);
источник
источник
источник
Int16
.