Исходное сообщение: Hi!
Зашифрованное сообщение: Qly Расшифрованное сообщение: Hi!
Как видите, в результате выполнения двух последовательностей поразрядных операций исключающее ИЛИ получается расшифрованное сообщение. (Еще раз напомним, что такое шифрование не имеет никакой практической ценности, поскольку оно, в сущности, ненадежно.)
Поразрядный унарный оператор НЕ (или оператор дополнения до 1) изменяет на обратное состояние всех двоичных разрядов операнда. Так, если некоторое целое значение А имеет комбинацию двоичных разрядов 1001 0110, то в результате поразрядной операции ~А получается значение с комбинацией двоичных разрядов 0110 1001.
В следующем примере программы демонстрируется применение поразрядного оператора НЕ с выводом некоторого числа и его дополнения до 1 в двоичном коде.
// Продемонстрировать применение поразрядного унарного оператора НЕ.
Using System;
class NotDemo {
static void Main() { sbyte b = -34;
}
Console.WriteLine ();
// обратить все биты b = (sbyte) ~b;
}
}
}
Результат выполнения этой программы приведен ниже.
Операторы сдвига
В C# имеется возможность сдвигать двоичные разряды, составляющие целое значение, влево или вправо на заданную величину. Для этой цели в C# определены два приведенных ниже оператора сдвига двоичных разрядов.
«
Сдвиг влево
>>
Сдвиг вправо
Ниже приведена общая форма для этих операторов:
значение «число_битов значение» число_битов
где число_битов — это число двоичных разрядов, на которое сдвигается указанное зна чение.
При сдвиге влево все двоичные разряды в указываемом значении сдвигаются на одну позицию влево, а младший разряд сбрасывается в нуль. При сдвиге вправо все двоичные разряды в указываемом значении сдвигаются на одну позицию вправо. Если вправо сдвигается целое значение безвнака, то старший разряд сбрасывается в нуль. А если вправо сдвигается целое значение со знаком, то разряд знака сохраняется. Напомним, что для представления отрицательных чисел старший разряд целого числа устанавливается в 1. Так, если сдвигаемое значение является отрицательным, то при каждом сдвиге вправо старший разряд числа устанавливается в 1. А если сдвигаемое значение является положительным, то при каждом сдвиге вправо старший разряд числа сбрасывается в нуль.
При сдвиге влево и вправо крайние двоичные разряды теряются. Восстановить потерянные при сдвиге двоичные разряды нельзя, поскольку сдвиг в данном случае не является циклическим.
Ниже приведен пример программы, наглядно демонстрирующий действие сдвига влево и вправо. В данном примере сначала задается первоначальное целое значение, равное 1. Это означает, что младший разряд этого значения установлен. Затем это целое значение сдвигается восемь раз подряд влево. После каждого сдвига выводятся восемь младших двоичных разрядов данного значения. Далее процесс повторяется, но на этот раз 1 устанавливается на позиции восьмого разряда, а по существу, задается целое значение 128, которое затем сдвигается восемь раз подряд вправо.
// Продемонстрировать применение операторов сдвига.
Using System;
class ShiftDemo {
static void Main() { int val = 1;
for(int i = 0; i < 8; i++) {
for(int t=128; t > 0; t = t/2) {
if((val & t)!= 0) Console.Write("1 "); if((val & t) == 0) Console.Write("0 ");
}
Console.WriteLine();
val = val <<1; // сдвиг влево
}
Console.WriteLine(); val = 128;
for(int i = 0; i < 8; i++) {
for(int t=128; t > 0; t = t/2) {
if((val & t)!= 0) Console.Write("1 "); if((val & t) == 0) Console.Write("0 ");
}
Console.WriteLine();
val = val >>1; // сдвиг вправо
}
}
}
Результат выполнения этой программы выглядит следующим образом.
Двоичные разряды соответствуют форме представления чисел в степени 2, и поэтому операторы сдвига могут быть использованы для умножения или деления целых значений на 2. Так, при сдвиге вправо целое значение удваивается, а при сдвиге влево — уменьшается наполовину. Разумеется, все это справедливо лишь в том случае, если крайние разряды не теряются при сдвиге в ту или иную сторону. Ниже приведен соответствующий пример.
// Применить операторы сдвига для умножения и деления на 2.
Using System;
class MultDiv {
static void Main() { int n;
n = 10;
Console.WriteLine("Значение переменной n: " + n);
// Умножить на 2.
n = n << l^-
Console.WriteLine ();
// Установить переменную n в исходное состояние, n = 10;
Console.WriteLine("Значение переменной n: " + n);
// Умножить на 2 тридцать раз. n = п << 30; // данные теряются
Console.WriteLine("Значение переменной п после " +
"сдвига на 30 позиций влево: " + п);
}
}