Главная страница
Навигация по странице:

  • Оператор | обычно используют для установки заданных битов переменной в единицу.

  • Оператор обычно применяют, чтобы обнулить один или несколько битов.

  • Операции с битами. Операции с битами


    Скачать 44.5 Kb.
    НазваниеОперации с битами
    Дата21.04.2022
    Размер44.5 Kb.
    Формат файлаdoc
    Имя файлаОперации с битами.doc
    ТипДокументы
    #489414



    Операции с битами

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

       В Си существуют 6 операторов для манипулирования битами. Их можно применять к любым целочисленным знаковым или беззнаковым типам переменных.


    <<  - сдвиг влево
    >>  - сдвиг вправо

       -  поразрядная инверсия
    |    - поразрядное ИЛИ
    &  - поразрядное И
    ^   -  поразрядное исключающее ИЛИ

    _______________ сдвиг влево << _______________


       Сдвигает число на n разрядов влево. Старшие n разрядов при этом исчезают, а младшие n  разрядов заполняются нулями.

            
            unsigned char tmp = 3;  //0b00000011    
            tmp = tmp << 1;   
            //теперь в переменной tmp число 6 или 0b00000110
            
            tmp = tmp << 3;
            //теперь в переменной tmp число 48  или 0b00110000

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

            tmp = 7;  //0b00000111    
            tmp <<= 2; //сокращенный вариант записи
            //теперь в переменной tmp число 28 или 0b00011100

    Операция сдвига влево на n разрядов эквивалентна умножению переменной на 2n.

    _______________ сдвиг вправо >> _______________


       Сдвигает число на n разрядов вправо. Младшие n разрядов при этом теряются. Заполнение старших n  разрядов зависит от типа переменной и ее значения. Старшие n разрядов заполняются нулями в двух случаях – если переменная беззнакового типа или если переменная знаковая и ее текущее значение положительное. Когда переменная знаковая и ее значение отрицательное – старшие разряды заполняются единицами.    


    Пример для беззнаковой переменной

            unsigned char tmp = 255;  //0b11111111
            tmp = tmp >> 1;
            //теперь в переменной tmp число 127 или 0b01111111
            
            tmp >>=  3;  //сокращенный вариант записи
            //теперь в переменной tmp число 15 или 0b00001111

    Пример для переменной знакового типа
            
            int tmp = 3400; //0b0000110101001000
            tmp >>= 2;
            //теперь в переменной число 850 или 0b0000001101010010

            tmp = -1200; //0b1111101101010000
            tmp >>= 2;
            //теперь в tmp число -600 или 0b1111111011010100
            //видите - два старших разряда заполнились единицами

       Операция сдвига вправо на n разрядов эквивалентна делению на 2n. При этом есть некоторые нюансы. Если потерянные младшие разряды содержали единицы, то результат подобного “деления” получается грубоватым.

    Например    9/4 = 2,5         а 9>>2      (1001>>2)    равно 2
                      11/4 = 2,75     а 11>>2      (1011>>2)    равно 2    
                      28/4 = 7          а 28>>2    (11100>>2)    равно 7        
    Во втором случае ошибка больше, потому что оба младших разряда единицы. В третьем случае ошибки нет, потому что потерянные разряды нулевые.

    _______________поразрядная инверсия

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


            unsigned char tmp =  94;     //0b01011110
            tmp = tmp;
            //теперь в переменной tmp число 161 или 0b10100001
            tmp = tmp;
            //теперь в tmp снова число 94 или 0b01011110

    _______________ поразрядное ИЛИ | ______________  


     

    Оператор | осуществляет операцию логического ИЛИ между соответствующими битами  двух операндов. Результатом операции логического ИЛИ между двумя битами будет 0 только в случае, если оба бита равны 0. Во всех остальных случаях результат будет 1. Это проиллюстрировано в табице истинности.

      

    Оператор | обычно используют для установки заданных битов переменной в единицу.
            
        tmp = 155
        tmp = tmp | 4; //устанавливаем в единицу второй бит переменной tmp

        155     0b10011011    
    |
            4     0b00000100    
        159     0b10011111

       Использовать десятичные числа для установки битов довольно неудобно. Гораздо удобнее это делать с помощью операции сдвига влево <<.


        tmp = tmp | (1<<4); //устанавливаем в единицу четвертый бит переменной tmp

       Читаем справа налево – сдвинуть единицу на четыре разряда влево, выполнить операцию ИЛИ между полученным числом и значением переменной tmp, результат присвоить переменной tmp.
    Установить несколько битов в единицу можно так
        tmp = tmp | (1<<7)|(1<<5)|(1<<0);
       //устанавливаем в единицу седьмой, пятый и нулевой биты переменной tmp
        
    С помощью составного оператора присваивания  |= можно сделать запись компактней.

        tmp |= (1<<4);
        tmp |= (1<<7)|(1<<5)|(1<<0);

    _______________ побитовое И & _______________






     

       Оператор & осуществляет операцию логического И между соответствующими битами двух операндов. Результатом операции логического И между двумя битами будет 1 только в том случае, если оба бита равны 1. Во всех других случаях результат будет 0. Это проиллюстрировано в таблице истинности.  

    Оператор & обычно применяют, чтобы обнулить один или несколько битов.
        
        tmp = 155;        
        tmp = tmp & 247; //обнуляем третий бит переменной tmp

        155        0b10011011    
    &
        247        0b11110111    
        147        0b10010011
    Видите, третий бит стал равен 0, а остальные биты не изменились.
    Обнулять биты, используя десятичные цифры, неудобно. Но можно облегчить себе жизнь, воспользовавшись операторами << и
        tmp = 155;
        tmp = tmp & ((1<<3)); //обнуляем третий бит
    1<<3                          0b00001000
    (1<<3)                     0b11110111
    tmp & ((1<<3))        0b10011011 & 0b11110111
    результат                    0b10010011

       Читаем справа налево – сдвинуть единицу на три разряда влево, выполнить инверсию полученного числа, выполнить операцию & между значением переменной tmp и проинвертированным числом, результат присвоить переменной tmp.
    Обнулить несколько битов можно так

        tmp = tmp & (((1<<3)|(1<<5)|(1<<6))); //обнуляем третий, пятый и шестой биты

       Здесь сначала выполняются операции сдвига, потом операции поразрядного ИЛИ, затем инверсия, поразрядное И, присвоение результата переменной tmp.
    Используя составной оператор присваивания &= ,можно записать выражение более компактно
        tmp &= (((1<<3)|(1<<5)|(1<<6)));
       Как проверить установлен ли бит в переменной? Нужно обнулить все биты, кроме проверочного, а потом сравнить полученное значение с нулем    
       if ((tmp & (1<<2)) != 0 ){
          // блок будет выполняться, только если установлен
          // второй бит переменной tmp
       }
        if ((tmp & (1<<2)) == 0 ){
          // блок будет выполняться, только если не установлен
          // второй бит переменной tmp
        }
        _______________побитовое исключающее ИЛИ ^ _______________  


       Оператор ^ осуществляет операцию логического исключающего ИЛИ между соответствующими битами двух операндов. Результатом операции логического исключающего ИЛИ будет 0 в случае равенства битов. Во всех остальных случаях результат будет 1. Это проиллюстрировано в табице истинности.

       Оператор ^ применяется не так часто как остальные битовые операторы, но и для него находится работенка. Например, с помощью него можно инвертировать один или несколько битов переменной.


        tmp = 155;
        tmp = tmp ^ 8; // инвертируем четвертый бит переменой tmp
        
        155         0b10011011    
    ^
        8             0b00001000    
        147         0b10010011

    Четвертый бит изменил свое значение на противоположное, а остальные биты остались без изменений.

        tmp = tmp ^ 8; // опять инвертируем четвертый бит переменой tmp

        147         0b10010011    
    ^
        8             0b00001000    
        155         0b10011011

    Видите, четвертый бит снова изменил свое значение на противоположное.  
    Так записывать выражение намного удобнее
        tmp = tmp ^ (1<<3); // инвертируем третий бит переменой tmp
        
    А так и удобно и компактно
        tmp ^= (1<<4);  //инвертируем четверый бит

    Можно инвертировать несколько битов одновременно
        tmp ^= ((1<<4)|(1<<2)|(1<<1)); //инвертируем 4,2 и 1 биты   

        У поразрядного исключающего ИЛИ есть еще одно интересное свойство. Его можно использовать, для того чтобы поменять значения двух переменных местами. Обычно для этого требуется третья переменная.
    tmp = var1;
    var1 = var2;
    var2 = tmp;
    Но используя оператор ^  переставить значения можно так:
    var1 ^= var 2;
    var 2 ^= var 1;
    var 1 ^= var 2;


    написать администратору сайта