Побитовые операции
Язык С предлагает два вида побитовых операций: логические операции и операции сдвига. В последующих примерах мы будем записывать значения в двоичной системе, чтобы вы могли видеть, что происходит с битами. В действительной программе вы будете применять целочисленные переменные или константы в обычных формах. Например, вместо 00011001 будет использоваться запись 25, 031 или 0x19. В рассмат риваемых примерах мы будем применять 8-битовые числа с нумерацией битов слева направо от 0 до 7.
Манипулирование битами 633
побитовые логические операции
Четыре логических побитовых операции работают с целочисленными данными, включая тип char. Они называются побитовыми потому, что выполняются над каждым битом независимо от бита, находящегося слева или справа. Не путайте их с обычными логическими операциями (&&, || и !), которые имеют дело со значениями целиком.
Дополнение до единицы или побитовое отрицание: ~
Унарная операция ~ преобразует каждую единицу в ноль, а каждый ноль в единицу, как показано в следующем примере:
-(10011010) // выражение
(01100101) // результат
Предположим, что переменной val типа unsigned char присвоено значение 2. В двоичном виде 2 имеет вид 00000010. Тогда ~val будет иметь значение 11111101, или 253. Обратите внимание, что операция не изменяет значения переменной val, в точности как не изменяет значение val выражение 3 * val; значением val по-прежнему является 2, но создается новое значение, которое можно использовать или присваивать где-то в другом месте:
newval = -val; printf("%d", -val);
Если вы хотите изменить значение val на -val, применяйте следующий простой оператор присваивания:
val = -val;
Побитовая операция "И": &
Двоичная операция & создает новое значение за счет выполнения побитового сравнения двух операндов. Для каждой позиции результирующий бит будет равен 1, только если оба соответствующих бита в операндах равны 1. (В терминах истинный/ложный можно сказать, что результат будет истинным, только когда каждый из двух битовых операндов является истинным.) Таким образом, в результате вычисления выражения
(10010011) & (00111101) // выражение
получается следующее значение:
(00010001) // результат
Причина в том, что только нулевой и четвертый биты равны 1 в обоих операндах. В С также имеется операция “И”, объединенная с присваиванием: &=.
Оператор
val &= 0377;
дает такой же результат, как и следующий оператор:
val = val & 0377;
Побитовая операция “ИЛИ": |
Двоичная операция | создает новое значение за счет выполнения побитового сравнения двух операндов. Для каждой позиции бит будет равен 1, если любой из соответствующих битов в операндах равен 1. (В терминах истинный/ложный можно сказать, что результат будет истинным в случае, когда один или другой битовый операнд является истинным либо сразу оба.)
634 глава 15
Таким образом, в результате вычисления выражения
(10010011) | (00111101) // выражение
получается следующее значение:
(10111111) // результат
Причина в том, что биты во всех позициях кроме 6 имеют значение 1 в одном или в другом операнде (или в обоих). В С также существует операция “ИЛИ”, объединенная с присваиванием: |=. Оператор
val |= 0377;
дает тот же результат, что и следующий оператор:
val = val | 0377;
Побитовое "исключающее ИЛИ": *
Двоичная операция ^выполняет побитовое сравнение двух операндов. Для каждой позиции результирующий бит будет равен 1, если один или другой (но не оба) из соответствующих битов в операндах равен 1. (В терминах истинный/ложный можно сказать, что результат будет истинным в случае, когда один или другой битовый операнд является истинным, но не оба.) Таким образом, в результате вычисления выражения
(10010011) ^ (00111101) // выражение
получается следующее значение:
(10101110) // результат
Обратите внимание, что поскольку бит 0 равен 1 у обоих операндов, результирующий бит 0 получает значение 0.
В языке С также имеется операция “исключающее ИЛИ”, объединенная с присваиванием: ^=. Оператор
val ^= 0377;
дает тот же результат, что и следующий оператор:
val = val ^0377;
Случай применения: маски
Побитовая операция “И” часто используется с маской. Маска — это комбинация битов, в которой некоторые биты включены (1), а некоторые выключены (0). Чтобы понять, почему ее так назвали, давайте посмотрим, что происходит, когда мы объединяем какую-то величину с маской с применением операции &. Для примера предположим, что вы определили символическую константу MASK как 2 (т.е. 00000010), у которой ненулевым является только бит с номером 1. Тогда оператор
Читать дальше