Битовые операции для целочисленных операндов

В языке Си имеются шесть операторов (&, |, ^, ~, >>, <<), которые можно использовать в программе для манипулирования битами в целых числах.

Оператор & (поразрядное «И») выполняет операцию логического умножения отдельных одноименных разрядов двух операндов.

Оператор | (поразрядное «ИЛИ») реализует операцию логического сложения отдельных одноименных битов двух операндов.

Операторы & и |, которые работают с операндами побитно, следует отличать от логических операторов && и ||, которые оценивают каждый операнд целиком, равен он нулю или нет. Например, если переменная Var1 = 1, а переменная Var2 = 4, то результат побитовой операции (Var1 & Var2) будет равен нулю, а логической (Var1 && Var2) будет равен единице.

Оператор ^ (поразрядное исключающее «ИЛИ») реализует сложение по модулю 2 для одноименных разрядов.

Оператор инверсии ~ (поразрядное отрицание) инвертирует все биты переменной.

Операции сдвига перемещают разряды операнда влево (<<) или вправо (>>) на указанное число позиций.

Часто операции сдвига используют для быстрого умножения или деления операнда на степень двойки (2, 4, 8, …). Каждый сдвиг влево на один разряд приводит к умножению операнда на два, а каждый сдвиг вправо – к делению на два.

Рассмотрим более подробно битовые операции и их применение при программировании МК.

Оператор сдвига влево <<

Оператор сдвига влево <<выполняет поразрядный сдвиг числа влево. Его синтаксис:

Var1 = Var2 << Num;

где Var1 и Var2 – целочисленные переменные, а Nun – число разрядов для сдвига.

Двоичное значение переменной Var2 сдвигается влево на указанное количество разрядов Num с заполнением освобождающихся справа разрядов нулями. При выходе за старший разряд сдвигаемые биты теряются.

Если Var1 и Var2 – одна переменная, то можно использовать укороченную форму записи

Var <<= Num;

Пример:

unsigned char n = 0x01; // n = 0b00000001

n = n << 4; // n = 0b00010000

unsigned char m = 0x03; // m = 0b00000011

m <<= 2; // m = 0b00001100

Помимо переменных можно сдвигать числовые константы, например:

Unsigned char n;

n = 1 << 5;

В этом примере единица, представленная своим двоичным значением 0b00000001, сдвигается влево на пять разрядов, и переменная n принимает двоичное значение 0b00100000.

Оператор сдвига вправо >>

Оператор сдвига вправо >> выполняет поразрядный сдвиг числа вправо. Его син­таксис:

Var1 = Var2 >> Num;

Значение переменной Var2 сдвигается вправо на указанное количество разрядов Num с заполнением освободившихся разрядов слева нулями. Следует отметить, что данное утверждение верно, если переменная Var2 беззнакового типа, или если переменная знаковая и ее текущее значение положительное. Если переменная знаковая и ее значение отрицательное, то старшие разряды заполняются единицами. При выходе за нулевой разряд переменной сдвигаемые биты теряются.

Пример:

unsigned char n = 0x80; // n = 0b10000000

n = n >> 4; // n = 0b00001000

unsigned char m = 0xС0; // m = 0b11000000

m >>= 2; // m = 0b00110000

Оператор инверсии ~

Оператор ~ инвертирует каждый разряд операнда, т.е. заменяет 1 на 0 и наоборот. Этот оператор – унарный и применяется только к одному операнду.

Var1 = ~Var2;

Пример:

unsigned char n = 0xAA; // n = 0b10101010

n = ~n; // n = 0b01010101

Оператор логического умножения &

Оператор & производит над операндами логическую операцию пораз­рядного "И". Это значит, что разряд результата будет равен 1 только в том случае, когда соответствующие разряды обоих операндов содержат 1. В противном случае он будет равен 0.

Var1 = Var2 & Var3;

Пример:

Unsigned char a, b, c;

a = 0x55; // a = 0b01010101

b = 0x01; // b = 0b00000001

c = a & b; // с = 0b00000001

Оператор & часто используется для принудительной очистки заданных разрядов одного из операндов, для чего в качестве второго операнда задается так называемая маска, в которой разряды, требующие очистки, установлены в 0.

Пример:

Unsigned char a, mask;

a = 0x75; // a = 0b01110101

mask = 0x0F; // mask = 0b00001111

a = a & mask; // a = 0b00000101

Оператор логического сложения |

Оператор | производит над операндами логическую операцию пораз­рядного "ИЛИ". Это значит, что разряд результата будет равен 1, если 1 содержится в соответствующем разряде хотя бы одного операнда.

Var1 = Var2 | Var3;

Пример:

Unsigned char a, b, c;

a = 0x55; // a = 0b01010101

b = 0x81; // b = 0b10000001

c = a | b; // с = 0b11010101

Оператор | применяется для принудительной установки заданных разрядов одного из операндов, при этом во втором операнде задается маска, в которой разряды, подлежащие установке в единицу, равны 1.

 

Пример:

Unsigned char a, mask;

a = 0x05; // a = 0b00000101

mask = 0xF0; // mask = 0b11110000

a = a | mask; // a = 0b11110101

Оператор сложения по модулю 2 ^

Оператор ^ производит над операндами логическую операцию исклю­чающего "ИЛИ", при которой в каждый разряд результата записывается 1, если соответствующие разряды операндов различаются, и 0, если они совпадают.

Var1 = Var2 ^ Var3;

Пример:

Unsigned char a, b, c;

a = 0x55; // a = 0b01010101

b = 0x03; // b = 0b00000011

c = a^b; // с = 0b01010110

Оператор ^ используется для инверсии заданных битов одного из операндов и для этого во втором операнде задается маска, в которой биты, подлежащие инверсии, установлены в 1.

Пример:

Unsigned char a, mask;

a = 0x55; // a = 0b01010101

mask = 0xF0; // mask = 0b11110000

a = a^mask; // a = 0b10100101