Язык программирования Си (Ритчи, Керниган) - страница 45

Для иллюстрации некоторых побитовых операций рассмотрим функцию getbits(x, p, n), которая формирует поле в n битов, вырезанных из x, начиная с позиции p, прижимая его к правому краю. Предполагается, что 0-й бит - крайний правый бит, а n и p - осмысленные положительные числа. Например, getbits(x,4,3) вернет в качестве результата 4, 3 и 2-й биты значения x, прижимая их к правому краю. Вот эта функция:

>/* getbits: получает n бит, начиная с p-й позиции */

>unsigned getbits(unsigned x, int p, int n)

>{

> return (x ›› (p+1-n)) & ~(~0 ‹‹ n);

>}

Выражение x ›› (р+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), возвращающую значение x с инвертированными n битами, начиная с позиции p (остальные биты не изменяются).

Упражнение 2.8. Напишите функцию rightrot (x, n), которая циклически сдвигает x вправо на n разрядов.

2.10 Операторы и выражения присваивания

Выражение

>i = i + 2;

в котором стоящая слева переменная повторяется и справа, можно написать в сжатом виде:

>i += 2;

Оператор +=, как и =, называется оператором присваивания.

Большинству бинарных операторов (аналогичных + и имеющих левый и правый операнды) соответствуют операторы присваивания op=, где op - один из операторов

>+

>- 

>*

>/

>%

>‹‹

>››

>&

>^

>|

Если выр>1 и выр>2 - выражения, то

>выр>1 op= выр>2

Эквивалентно

>выр>1 = (выр>1) op (выр>2)

с той лишь разницей, что выр>1 вычисляется только один раз. Обратите внимание на скобки вокруг выр>2:

>x *= y + 1

эквивалентно

>x = x * (y + 1)

но не

>x=x*y+1

В качестве примера приведем функцию bitcount, подсчитывающую число единичных битов в своем аргументе целочисленного типа.

>/* bitcount: подсчет единиц в х */

>int bitcount(unsigned х)

>{

> int b;

> for (b = 0; х != 0; x ››= 1)

>  if (x & 01)

>   b++;

> return b;

>}

Независимо от машины, на которой будет работать эта программа, объявление аргумента x как unsigned гарантирует, что при правом сдвиге освобождающиеся биты будут заполняться нулями, а не знаковым битом.

Помимо краткости операторы присваивания обладают тем преимуществом, что они более соответствуют тому, как человек мыслит. Мы говорим "прибавить 2 к i" или "увеличить i на 2", а не "взять i, добавить 2 и затем вернуть результат в i", так что выражение i+=2 лучше, чем i=i+2. Кроме того, в сложных выражениях вроде