netlib.narod.ru< Назад | Оглавление | Далее >

2.9. Поразрядные операторы

В Си есть шесть операций для работы с битами. Их можно применять только к целочисленным операндам, т.е. к операндам типов 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< Назад | Оглавление | Далее >

Сайт управляется системой uCoz