×
Traktatov.net » Освой самостоятельно С++ за 21 день » Читать онлайн
Страница 447 из 448 Настройки

7. Какова разница между операторами | и || ?

Оператор | — это побитовое ИЛИ, а || — этологическое ИЛИ.

 Упражнения

1. Создайте защиту от повторного включения файла заголовка STRING.H.

#ifndef STRING_H

#define STRING_H

...

#endif

2. Напишите макрос assert(), который

• будет печатать сообщение об ошибке, а также имя файла и номер строки, если уровень отладки равен 2;

• будет печатать сообщение (без имени файла и номера строки), если уровень отладки равен 1;

• не будет ничего делать, если уровень отладки равен 0.

1: #include

2:

3: #ifndef DEBUG

4: #define ASSERT(x)

5: #elif DEBUG — 1

6: #define ASSERT(x)

7: if (! (x))

S: {

9:    cout << "ERROR!! Assert " << #x << " failed\n";

10: }

11: #elif DEBUG == 2

12: #define ASSERT(x)

13: if (! (x) )

14: {

15:    cout << " ERROR!! Assert " << #x << " failed\n";

16:    cout << " on line " << __LINE__ << "\n";

17:    cout << " in file " << __LINE__ << "\n";

18: }

19: #endif

3. Напишите макрос DPrint, который проверяет, определена ли лексема DEBUG, и, если да, выводит значение, передаваемое как параметр.

#ifndef DEBUG:

#define DPRINT(string)

#else

#define DPRINT(STRIN6) cout << #STRING:

#endif

4. Напишите программу, которая складывает два числа без использования операции сложения (+). Подсказка: используйте побитовые операторы!

Если рассмотреть сложение двух битов, то можно заметить, что ответ будет содержать два бита: бит результата и бит переноса. Таким образом, при сложении двух единиц в двоичной системе бит результата будет равен нулю, а бит переноса — единице. Если сложить два двоичных числа 101 и 001, получим следующие результаты:

101 // 5

001 // 1

110 // 6

Следовательно, если сложить два соответствующих бита (каждый из них равен единице), то бит результата будет равен 0, а бит переноса — 1. Если же сложить два сброшенных бита, то и бит результата, и бит переноса будут равны 0. Если сложить два бита, один из которых установлен, а другой сброшен, бит результата будет равен 1, а бит переноса — 0. Перед вами таблица, которая обобщает эти правила сложения

Левый бит lhs Правый бит rhs Перенос Результат

0 0 0 0

0 1 0 1

1 0 0 1

1 1 1 0

Рассмотрим логику бита переноса. Если оба суммируемых бита (lhs и rhs) равны 0 или хотя бы один из них равен 0, бит переноса будет равен 0. И только если оба бита равны 1, бит переноса будет равен 1. Такая ситуация в точности совпадает с определением побитового оператора И (&).

Если подобным образом рассмотреть логику бита результата, то окажется, что она совпадает с выполнением оператора побитового исключающего ИЛИ (^): если любой из суммируемых битов (но не оба сразу) равен I, бит результата равен 1, в противном случае — 0.

Полученный бит переноса добавляется к следуюшему значимому биту. Это можно реализовать либо итеративным проходом через каждый бит, либо использованием рекурсии.

#include

unsigned int add( unsigned int lhs, unsigned lnt rhs )

{

   unsigned int result, carry;

   while ( 1 )

   {

      result = lhs ^ rhs;

      carry = lhs & rhs;

      if ( carry == 0 )

         break;

      lhs = carry << 1;

      rhs = result;