netlib.narod.ru | < Назад | Оглавление | Далее > |
В Си есть шесть операций для работы с битами. Их можно применять только к целочисленным операндам, т.е. к операндам типов char, short, int и long, как знаковым так и беззнаковым.
& | — поразрядное логическое И. |
| | — поразрядное логическое ИЛИ. |
^ | — поразрядное ИСКЛЮЧАЮЩЕЕ ИЛИ. |
<< | — сдвиг влево. |
>> | — сдвиг вправо. |
~ | — поразрядное отрицание, НЕ (унарный оператор). |
Оператор & (поразрядное И) часто используется для обнуления некоторой группы разрядов. Например
n = n & 0177;
обнуляет в n все разряды, кроме младших семи.
Оператор | (поразрядное ИЛИ) применяется для установки отдельных разрядов в 1. Например
x = x | SET_ON;
устанавливает в результате единицы в тех разрядах, которым соответствуют единицы в SET_ON.
Оператор ^ (поразрядное ИСКЛЮЧАЮЩЕЕ ИЛИ) в каждый разряд результата запишет 1, если соответствующие разряды операндов имеют различные значения, и 0, когда они совпадают.
Поразрядные операторы & и | следует отличать от логических операторов && и ||, которые вычисляются слева направо и дают значение истинности. Например, если x равно 1, а y равно 2, то x & y равно нулю, а x && y равно единице.
Операторы << и >> сдвигают влево или вправо свой левый операнд на число разрядов, задаваемое правым операндом, который должен быть неотрицательным. Например, x << 2 сдвигает значение x влево на 2 разряда, заполняя освобождающиеся биты нулями, что эквивалентно умножению x на 4. Сдвиг вправо беззнаковой величины всегда сопровождается заполнением освобождающихся разрядов нулями. Сдвиг вправо числа со знаком на одних машинах происходит с распространением знака (арифметический сдвиг), а на других — с заполнением освобождающихся разрядов нулями (логический сдвиг).
Унарный оператор ~ осуществляет поразрядную инверсию своего операнда, преобразуя каждый единичный бит в нулевой и наоборот. Например,
x = x & ~077
обнуляет в x последние шесть разрядов. Заметим, что запись x & ~077 не зависит от размера операнда, и, следовательно, она лучше, чем запись x & 0177700, поскольку последняя подразумевает, что x занимает 16 битов. Независимая от типа машины форма записи ~077 не потребует дополнительных затрат времени при работе программы, так как ~077 это константное выражение, вычисляемое во время компиляции.
Для иллюстрации некоторых поразрядных операторов рассмотрим функцию getbits(x, p, n), которая вырезает из x поле в n битов, начиная с позиции p, прижимая их в результате к правому краю. Предполагается что нулевой бит — крайний правый, а n и p — осмысленные положительные значения. Например, getbits(x, 4, 3) вернет четвертый, третий и второй биты из x, разместив их во втором, первом и нулевом разрядах результата. Рассмотрим текст функции:
/* getbits: вырезает n бит, начиная с позиции p */ unsigned getbits (unsigned x, int p, int n) { return (x >> (p+1-n)) & ~(~0 << n); }
Выражение x >> (p+1-n) сдвигает нужное нам поле к правому краю. Константа ~0 состоит из одних единиц, и ее сдвиг влево на n бит (~0 << n) приведет к тому, что правый край этой константы займут n нулевых разрядов. Еще одна операция поразрядной инверсии ~ позволяет получить справа n единиц.
Упражнение 2-6 |
Напишите функцию setbits(x, p, n, y), возвращающую значение x, в котором n битов, начиная с позиции p, заменены на n правых разрядов из y. Остальные биты не изменяются. |
Упражнение 2-7 |
Напишите функцию invert(x, p, n), возвращающую значение х в котором инвертированы n битов, начиная с позиции p. Остальные биты не изменяются. |
Упражнение 2-8 |
Напишите функцию rightrot(x, n), которая циклически сдвигает x вправо на n разрядов. |
netlib.narod.ru | < Назад | Оглавление | Далее > |