Использование побитовых операций
Как уже говорилось, побитовые операции используются для обработки отдельных двоичных разрядов памяти. Для манипулирования отдельным битом необходимо научиться делать следующее:
· определять значение заданного бита;
· устанавливать значение заданного бита в значение 0 или 1;
· инвертировать значение заданного бита.
Это можно сделать так:
unsigneda = 1234; // Целое значение, битами которого мы будем управлять
unsignedshortn = 4;// Номер необходимого бита (от 0 до 31)
boolr; // Значение результата (0 или 1)
/* Узнаем, чему равен n-й бит (двоичный разряд) значения a. Результат поместим в переменную r */
r = a& (1U<<n);
cout<< "Разряд с номером " <<n<< " равен " <<r<<endl; //значение1
/* Установим n-й бит (двоичный разряд) значения aв0. Результат поместим в переменную а */
a = a& (~ (1U<<n));
cout<< "Значение а равно " <<a<<endl; //значение1218
/* Проверяем */
r = a& (1U<<n);
cout<< "Разряд с номером " <<n<< " равен " <<r<<endl; //значение0
/* Возвращаем n-й бит (двоичный разряд) значения a в 1. Результат поместим в переменную а*/
a = a | (1U<<n);
cout<< "Значение а равно " <<a<<endl; //значение1234
/* Проверяем */
r = a& (1U<<n);
cout<< "Разряд с номером " <<n<< " равен " <<r<<endl; //значение1
/* Инвертируем n-й бит (двоичный разряд) значения a. Результат поместим в переменную а */
a = a ^ (1U<<n);
cout<< "Значение а равно " <<a<<endl; //значение1218
/* Проверяем */
r = a& (1U<<n);
cout<< "Разряд с номером " <<n<< " равен " <<r<<endl; //значение0
/* Еще раз инвертируем n-й бит (двоичный разряд) значения a. Результат поместим в переменную а */
a = a ^ (1U<<n);
cout<< "Значение а равно " <<a<<endl; //значение1234
/* Проверяем */
r = a& (1U<<n);
cout<< "Разряд с номером " <<n<< " равен " <<r<<endl; //значение1
Изменяя значение переменной nв диапазоне от 0 до 31 можно выполнить все эти действия над любым битом переменной aкакое бы значение она не содержала.
Таким образом, для того, чтобы узнать, чему равен двоичный разряд с номером nв значении переменной a, мы воспользовались выражением a& (1U<<n).
Иллюстрация вычисления этого выражения:
Номер разряда: 31 30 … 11 10 9 8 7 6 5 4 3 2 1 0
1U: 0 0 … 0 0 0 0 0 0 0 0 0 0 0 1 = 1
1U<<n: 0 0 … 0 0 0 0 0 0 0 1 0 0 0 0
Значение a: 0 0 … 0 1 0 0 1 1 0 1 0 0 1 0 = 1234
a& (1U<<n): 0 0 … 0 0 0 0 0 0 0 1 0 0 0 0 = 16
Результатом вычисления этого выражения является целое значение не равное 0. Операция присваивания этого значения логической переменной r автоматически преобразует целое значение 16 в логическое значение true (т.е. 1).
Если бы значение a имело бы разряд с номером 4 равным 0, то результатом вычисления этого выражения было бы значение 0. При выполнении операции присваивания это значение было бы преобразовано в логическое значение false (т.е. 0).
Для установки значения разряда с номером n в переменной aв значение 0 используется выражение a& (~ (1U<<n)).
Иллюстрация вычисления этого выражения:
Номер разряда: 31 30 … 11 10 9 8 7 6 5 4 3 2 1 0
1U: 0 0 … 0 0 0 0 0 0 0 0 0 0 0 1 = 1
1U<<n: 0 0 … 0 0 0 0 0 0 0 1 0 0 0 0
~ (1U << n): 1 1 … 1 1 1 1 1 1 1 0 1 1 1 1
Значение a: 0 0 … 0 1 0 0 1 1 0 1 0 0 1 0 = 1234
a& (1U<<n): 0 0 … 0 1 0 0 1 1 0 0 0 0 1 0 = 1218
Для установки значения разряда с номером n в переменной aв значение 1 используется выражение a|(1U<<n).
Иллюстрация вычисления этого выражения:
Номер разряда: 31 30 … 11 10 9 8 7 6 5 4 3 2 1 0
1U: 0 0 … 0 0 0 0 0 0 0 0 0 0 0 1 = 1
1U<<n: 0 0 … 0 0 0 0 0 0 0 1 0 0 0 0
Значение a: 0 0 … 0 1 0 0 1 1 0 0 0 0 1 0 = 1218
a | (1U<<n): 0 0 … 0 1 0 0 1 1 0 1 0 0 1 0 = 1234
Для инвертирования значения разряда с номером n в переменной aиспользуется выражение a^(1U<<n).
Иллюстрация вычисления этого выражения при a = 1218:
Номер разряда: 31 30 … 11 10 9 8 7 6 5 4 3 2 1 0
1U: 0 0 … 0 0 0 0 0 0 0 0 0 0 0 1 = 1
1U<<n: 0 0 … 0 0 0 0 0 0 0 1 0 0 0 0
Значение a: 0 0 … 0 1 0 0 1 1 0 0 0 0 1 0 = 1218
a ^ (1U << n): 0 0 … 0 1 0 0 1 1 0 1 0 0 1 0 = 1234
Но, если a = 1234, то:
Номер разряда: 31 30 … 11 10 9 8 7 6 5 4 3 2 1 0
1U: 0 0 … 0 0 0 0 0 0 0 0 0 0 0 1 = 1
1U<<n: 0 0 … 0 0 0 0 0 0 0 1 0 0 0 0
Значение a: 0 0 … 0 1 0 0 1 1 0 1 0 0 1 0 = 1234
a ^ (1U<<n): 0 0 … 0 1 0 0 1 1 0 0 0 0 1 0 = 1218
Примеры применения побитовых операций.
Примеры:
unsigned a = 20, n = 3, r;
r = a << n;
cout<<r<<endl; //На экран выведено 160
r = a >> n;
cout<<r<<endl; //На экран выведено 2
Иллюстрация:
Номер разряда: 31 30 … 8 7 6 5 4 3 2 1 0
Значение a: 0 0 … 0 0 0 0 1 0 1 0 0 = 20
Операция: a<<n
Значение r: 0 0 … 0 1 0 1 0 0 0 0 0 = 160
Операция: a>>n
Значение r: 0 0 … 0 0 0 0 0 0 0 1 0 = 2
inta = 14, b = 7, r;
r = a&b;
cout<<r<<endl; //На экран выведено6
r = a | b;
cout<<r<<endl; //На экран выведено15
r = a ^ b;
cout<<r<<endl; //На экран выведено9
Иллюстрация:
Номер разряда: 31 30 … 8 7 6 5 4 3 2 1 0
Значение a: 0 0 … 0 0 0 0 0 1 1 1 0 = 14
Значение b: 0 0 … 0 0 0 0 0 0 1 1 1 = 7
Операция: a&b
Значение r: 0 0 … 0 0 0 0 0 0 1 1 0 = 6
Операция: a | b
Значение r: 0 0 … 0 0 0 0 0 1 1 1 1 = 15
Операция: a ^ b
Значение r: 0 0 … 0 0 0 0 0 1 0 0 1 = 9
unsigneda = 1234; // Целое значение, битами которого мы будем управлять
unsignedshortn = 4;// Номер необходимого бита (от 0 до 31)
boolr; // Значение результата (0 или 1)
/* Узнаем, чему равен n-й бит (двоичный разряд) значения a. Результат поместим в переменную r */
r = a& (1U<<n);
cout<< "Разряд с номером " <<n<< " равен " <<r<<endl; //значение1
Иллюстрация вычисления этого выражения:
Номер разряда: 31 30 … 11 10 9 8 7 6 5 4 3 2 1 0
1U: 0 0 … 0 0 0 0 0 0 0 0 0 0 0 1 = 1
1U<<n: 0 0 … 0 0 0 0 0 0 0 1 0 0 0 0
Значение a: 0 0 … 0 1 0 0 1 1 0 1 0 0 1 0 = 1234
a& (1U<<n): 0 0 … 0 0 0 0 0 0 0 1 0 0 0 0 = 16