Ответ Марка, кажется, в силу того, что он был принят, касается исходной проблемы ОП. Однако из текста вопроса мне не совсем понятно, почему. Это все еще требует замены байтов, а не пар байтов, как это делает ответ Марка. Я не знаю ни одного достаточно распространенного сценария, в котором замена битов 16 за раз имеет смысл или полезна.
Для заявленных требований ИМХО разумнее было бы написать так:
int target = 250; // 0x00FA
// swap the bytes of target
target = ((target << 8) | (target >> 8)) & 0xFFFF;
// target now is 0xFA00
string hexString = target.ToString("X4");
Обратите внимание, что вышеприведенное предполагает, что мы фактически имеем дело с 16-битными значениями, хранящимися в 32-битной переменной int
. Он будет обрабатывать любой ввод в 16-битном диапазоне (обратите внимание на необходимость маскировать старшие 16 бит, так как они устанавливаются в ненулевые значения оператором <<
).
При замене 32-битных значений потребуется что-то вроде этого:
int target = 250; // 0x00FA
// swap the bytes of target
target = (int)((int)((target << 24) & 0xff000000) |
((target << 8) & 0xff0000) |
((target >> 8) & 0xff00) |
((target >> 24) & 0xff));
// target now is 0xFA000000
string hexString = target.ToString("X8");
Опять же, маскирование требуется, чтобы изолировать биты, которые мы перемещаем в определенные позиции. Приведение результата << 24
обратно к int
перед операцией ИЛИ с другими тремя байтами необходимо, потому что 0xff000000
является литералом uint
(UInt32
) и вызывает расширение выражения &
до long
(Int64
). В противном случае вы получите предупреждения компилятора с каждым из операторов |
.
В любом случае, поскольку это чаще всего происходит в сетевых сценариях, стоит отметить, что .NET предоставляет вспомогательные методы, которые могут помочь в этой операции: HostToNetworkOrder()
и NetworkToHostOrder()
. В этом контексте «сетевой порядок» всегда имеет порядок байтов с обратным порядком байтов, а «порядок хоста» — это любой порядок байтов, используемый на компьютере, на котором размещен текущий процесс.
Если вы знаете, что получаете данные с обратным порядком байтов, и хотите иметь возможность интерпретировать их как правильные значения в своем процессе, вы можете вызвать NetworkToHostOrder()
. Аналогичным образом, если вам нужно отправить данные в контексте, где ожидается обратный порядок байтов, вы можете вызвать HostToNetworkOrder()
.
Эти методы работают только с тремя основными целочисленными типами: Int16
, Int32
и Int64
(в C# short
, int
и long
соответственно). Они также возвращают тот же тип, который был передан им, поэтому вы должны быть осторожны с расширением знака. Исходный пример в вопросе можно решить так:
int target = 250; // 0x00FA
// swap the bytes of target
target = IPAddress.HostToNetworkOrder((short)target) & 0xFFFF;
// target now is 0xFA00
string hexString = target.ToString("X4");
Опять же, требуется маскирование, потому что в противном случае значение short
, возвращаемое методом, будет расширено по знаку до 32 бит. Если в результате установлен бит 15 (т. е. 0x8000
), то окончательное значение int
в противном случае также будет иметь свои старшие 16 бит. Это можно решить без маскирования, просто используя более подходящие типы данных для переменных (например, short
, когда ожидается, что данные будут подписанными 16-битными значениями).
Наконец, я отмечу, что методы HostToNetworkOrder()
и NetworkToHostOrder()
, поскольку они только меняют местами байты, эквивалентны друг другу. Они оба меняют местами байты, когда архитектура машины имеет обратный порядок байтов† . И действительно, реализация .NET просто для NetworkToHostOrder()
для вызова HostToNetworkOrder()
. Существует два метода, в основном для того, чтобы API .NET соответствовал исходному API сокетов BSD, который включал такие функции, как htons()
и ntohs()
, и этот API, в свою очередь, включал функции для обоих направлений преобразования, главным образом, чтобы в коде было ясно, получает ли кто-то данные из сети или отправка данных в сеть.
† И ничего не делать, когда архитектура машины имеет обратный порядок байтов, они бесполезны в качестве обобщенных функций перестановки байтов. Скорее ожидается, что сетевой протокол всегда будет с обратным порядком байтов, и эти функции используются для обеспечения того, чтобы байты данных менялись местами в соответствии с любой архитектурой машины.
person
Peter Duniho
schedule
08.08.2016