Читаем Программирование. Принципы и практика использования C++ Исправленное издание полностью

  Вывод: вы можете использовать целые числа без знака вместо целых чисел со знаком (включая обычную арифметику), но избегайте этого, поскольку это ненадежно и приводит к ошибкам.

• Никогда не используйте целые числа без знака просто для того, чтобы получить еще один бит точности.

• Если вам необходим один дополнительный бит, то вскоре вам потребуется еще один.

  К сожалению, мы не можем совершенно избежать использования арифметики целых чисел без знака.

• Индексирование контейнеров в стандартной библиотеке осуществляется целыми числами без знака.

• Некоторые люди любят арифметику чисел без знака. 

<p id="AutBody_Root500"><strong>25.5.4. Манипулирование битами</strong></p>

  Зачем вообще нужно манипулировать битами? Ведь многие из нас предпочли бы этого не делать. “Возня с битами” относится к низкому уровню и открывает возможности для ошибок, поэтому, если у нас есть альтернатива, следует использовать ее. Однако биты настолько важны и полезны, что многие программисты не могут их игнорировать. Это может звучать довольно грозным и обескураживающим предупреждением, но оно хорошо продумано. Некоторые люди действительно любят возиться с битами и байтами, поэтому следует помнить, что работа с битами иногда необходима (и даже может принести удовольствие), но ею не следует злоупотреблять. Процитируем Джона Бентли: “Люди, развлекающиеся с битами, будут биты” (“People who play with bits will be bitten”).

Итак, когда мы должны манипулировать битами? Иногда они являются естественными объектами нашей предметной области, поэтому естественными операциями в таких приложениях являются операции над битами. Примерами таких приложений являются индикаторы аппаратного обеспечения (“влаги”), низкоуровневые коммуникации (в которых мы должны извлекать значения разных типов из потока байтов), графика (в которой мы должны составлять рисунки из нескольких уровней образов) и кодирование (подробнее о нем — в следующем разделе).

Для примера рассмотрим, как извлечь (низкоуровневую) информацию из целого числа (возможно, из-за того, что мы хотим передать его как набор байтов через двоичный механизм ввода-вывода).

void f(short val) // пусть число состоит из 16 битов, т.е. 2 байта

{

  unsigned char left = val>>8;    // крайний левый

                                  // (самый старший) байт

  unsigned char right = val&0xff; // крайний правый

                                  // (самый младший) байт

  // ...

  bool negative = val&0x8000;     // знаковый бит

  // ...

}

Такие операции не редкость. Они известны как “сдвиг и наложение маски” (“shift and mask”). Мы выполняем сдвиг (“shift”), используя операторы << или >>, чтобы переместить требуемые биты вправо (в младшую часть слова), где ними легко манипулировать. Мы накладываем маску (“mask”), используя оператор “и” (&) вместе с битовой комбинацией (в данном случае 0xff), чтобы исключить (установить равными нулю) биты, нежелательные в результате.

При необходимости именовать биты часто используются перечисления. Рассмотрим пример.

enum Printer_flags {

  acknowledge=1,

  paper_empty=1<<1,

  busy=1<<2,

  out_of_black=1<<3,

  out_of_color=1<<4,

  // ...

};

Этот код определяет перечисление, в котором каждый элемент равен именно тому значению, которому соответствует его имя.

Такие значения полезны, потому что они комбинируются совершенно независимо друг от друга.

unsigned char x = out_of_color | out_of_black; // x = 24 (16+8)

x |= paper_empty; // x = 26 (24+2)

Отметим, что оператор |= можно прочитать как “установить бит” (или “установить некоторый бит”). Значит, оператор & можно прочитать как “установлен ли бит?” Рассмотрим пример.

if (x& out_of_color) { // установлен ли out_of_color? (Да, если

                       // установлен)

// ...

}

Оператор & по-прежнему можно использовать для наложения маски.

unsigned char y = x &(out_of_color | out_of_black); // y = 24

Теперь переменная y содержит копию битов из позиций 4 и 4 числа x (out_of_color и out_of_black).

Очень часть переменные типа enum используются как набор битов. При этом необходимо выполнить обратное преобразование, чтобы результат имел вид перечисления. Рассмотрим пример.

// необходимо приведение

Flags z = Printer_flags(out_of_color | out_of_black);

Перейти на страницу:

Похожие книги

Programming with POSIX® Threads
Programming with POSIX® Threads

With this practical book, you will attain a solid understanding of threads and will discover how to put this powerful mode of programming to work in real-world applications. The primary advantage of threaded programming is that it enables your applications to accomplish more than one task at the same time by using the number-crunching power of multiprocessor parallelism and by automatically exploiting I/O concurrency in your code, even on a single processor machine. The result: applications that are faster, more responsive to users, and often easier to maintain. Threaded programming is particularly well suited to network programming where it helps alleviate the bottleneck of slow network I/O. This book offers an in-depth description of the IEEE operating system interface standard, POSIX (Portable Operating System Interface) threads, commonly called Pthreads. Written for experienced C programmers, but assuming no previous knowledge of threads, the book explains basic concepts such as asynchronous programming, the lifecycle of a thread, and synchronization. You then move to more advanced topics such as attributes objects, thread-specific data, and realtime scheduling. An entire chapter is devoted to "real code," with a look at barriers, read/write locks, the work queue manager, and how to utilize existing libraries. In addition, the book tackles one of the thorniest problems faced by thread programmers-debugging-with valuable suggestions on how to avoid code errors and performance problems from the outset. Numerous annotated examples are used to illustrate real-world concepts. A Pthreads mini-reference and a look at future standardization are also included.

David Butenhof

Программирование, программы, базы данных