C Урок 15. Побитовые операторы. Часть 2



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

Переходим в функцию main() и объявим там сначала строковый массив, в котором будет храниться полученная строка в результате работы нашей функции, когда мы её будем вызывать

 

 

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

 

 

Я не давал такие типы констант в уроке по константам, потому что не каждый компилятор умеет работать с двоичными типами, но наш gcc оказался в этом плане умным.

Произведём операцию & между значениями наших переменных и результат присвоим другой переменной того же типа

 

 

С помощью нашей функции отобразим и наши операнды в двоичном виде и результат тоже

 

 

Соберём код и посмотрим результат работы нашего кода

 

 

Всё отлично сработало — и операция и функция.

Закомментируем весь написанный нами код в функции main() кроме объявления массива и проделаем аналогичные действия с такими же операндами, но уже с применением операции ИЛИ

 

 

Проверим работу кода

 

 

Также всё сработало.

 

 

Теперь операция Исключающее ИЛИ

 

 

Проверим, как это работает

 

Также всё отлично сработало.

Теперь проверим работу со сдвигами. Сдвигать будем одно и то же число, но в разные стороны и на разное количество пунктов

 

 

Посмотрим работу операций

 

 

Все операции работают и наглядно показываются в консоли.

 

 

Теперь оставшийся унарный оператор отрицания

 

 

Проверяем

 

 

Все нули превратились в единицы, а единицы — в нули.

Теперь покажу некоторый смысл наших побитовых операций в тех случаях, когда нам нужно сбросить или выставить определённые биты в каком-то числе. Такой стиль написания кодах при таких операциях мы используем в ситуациях, когда нам нужно сбросить некоторые биты регистров контроллеров или их установить. Кто смотрел мои уроки по контроллерам, тот это видел.

Сначала добавим вот такие вот макросы

 

 

Это будут номера битов в байте.

Добавим вот такой вот код в функцию main()

 

 

Не правда ли, красиво и наглядно вот это?

 

a |= ((1<<BIT3) | (1<<BIT4));

 

Здесь происходит присваивание одновременно с операцией ИЛИ. Такой вид присваивания мы будем проходить в одном из следующих уроков. А вообще здесь сначала мы получаем два числа, в которых все нули кроме того бита, который нам надо установить в значении переменной a. Такие числа получаются засчёт того, что мы единицу, являющуюся левым операндом в обоих данных операциях сдвигаем на такое количество пунктов, бит с номером которого мы и хотим установить. Некоторые путают, что будто мы макрос BIT3 или BIT4 сдвигаем на 1 влево. Кто не знаком с операциями сдвига, того может охватить вполне такой оптический обман. Затем результаты наших обоих операций также складываются логически при помощи операции ИЛИ и результатом всего выражения и будет число с установленными битами с индексами наших макросов. Затем происходит операция ИЛИ между значением переменной a, которое она имела до нашей операции с результатом выражения справа и результат данной операции присваивается опять же переменной a. Таким образом, в данной переменной установятся соответствующие биты, а остальные биты не изменят своего состояния.

Проверим, как сработает наш код

 

 

Всё сработало. Биты 3 и 4 установились, а остальные не тронулись.

Теперь, наоборот, попытаемся сбросить два бита, не трогая остальные. Делается это уже вот так

 

 

Опять же об данной операции стоит отдельно поговорить

 

a &= ~((1<<BIT6) | (1<<BIT1));

 

Происходит всё аналогично. Мы сначала, так сказать, готовим для сброса битов маску. Готовится число с теми установленными битами в байте, которые нам надо, наоборот, сбросить.

Затем мы это число инвертируем с помощью операции отрицания (оператор тильда ~). Затем уже инвертированное число, в котором будут все биты равны единице, за исключением тех, которые надо сбросить. С данным числом и со значением переменной a мы уже производим операцию логического умножения И, в результате которой сбросятся биты с такими номерами, в байтах под номером которых в левом операнде будут нули. А затем результат данной операции опять присвоится переменной a.

Проверим работу нашего кода

 

 

Отлично. Биты под номером 6 и 1 сбросились.

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

Итак, на данном занятии мы познакомились с побитовыми операторами, а затем неплохо попрактиковались, за счёт чего многие, я надеюсь, прочувствовали не только, как работать с данными операторами, но и немного поняли их практический смысл. Конечно же, это не всё, мы с битами будем обязательно впоследствии работать много.

Всем спасибо за внимание!

 

 

Предыдущая часть Программирование на C Следующий урок

 

Исходный код

 

 

Смотреть ВИДЕОУРОК (нажмите на картинку)

 

C Побитовые операторы

2 комментария на “C Урок 15. Побитовые операторы. Часть 2
  1. Иван:

    ну и наворотил автор с int2bin. может так проще:
    strcpy(in_str,»0b00000000");
    if (x && 0x80) in_str[2] = '1';
    for (unsigned char i = 0; i<7; i++)
    {
    x<<=1;
    if (x & 0x80) in_str[i+3] = '1';
    }
    интересно, как в отладчике сравнить 2 программы по времени исполнения

  2. Женя:

    Добрый вечер, Подскажите как правильно передать переменную a=0b11000011 через scanf()?

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

*