Форум программистов, компьютерный форум, киберфорум
Наши страницы
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг 4.75/12: Рейтинг темы: голосов - 12, средняя оценка - 4.75
sab1ch
BrainOverflow
124 / 128 / 63
Регистрация: 31.03.2013
Сообщений: 556
1

Для чего нужны битовые операции?

10.02.2016, 17:25. Просмотров 2199. Ответов 24
Метки нет (Все метки)

Здравствуйте.
Дошел в книге Стенли до битовых операций, но никак не могу понять их предназначение.
Где вообще они используются и как с ними работать? Объясните, если это возможно, на простых примерах.
0
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
10.02.2016, 17:25
Ответы с готовыми решениями:

Битовые операции - перемещение бит для unsigned int
Помогите разобраться, задание: Создайте функцию, которая перемещает биты...

Битовые операции, битовые поля.
Здравствуйте! Еслть 4 диапазона чисел: 0-100, 0-100, 0-6000, 0-3. Сделать в...

Битовые операции. Написать программу для хранения в битовом поле информации о конфигурации компьютера.
1. Написать программу для хранения в битовом поле информации о конфигурации...

Битовые операции и операции смещения языка С
Доброго времени суток господа,помогите пожалуйста.Есть 2 кода к задаче,первый...

Битовые операции (написать функцию для сброса в ноль двух битов с заданными номерами в коде символа)
Вот наткнулся на интересную задачку: "Написать функцию для сброса в ноль двух...

24
DavidTs
3 / 3 / 8
Регистрация: 25.11.2015
Сообщений: 127
10.02.2016, 17:35 2
Sabnik18, Битовые операции широко используются в ассемблере, в stl есть контейнер bitset. Вот здесь есть простые примеры. http://www.c-cpp.ru/books/bitovye-operatory
0
sab1ch
BrainOverflow
124 / 128 / 63
Регистрация: 31.03.2013
Сообщений: 556
10.02.2016, 17:47  [ТС] 3
DavidTs, а для чего они нужны вообще, если честно: "в stl есть контейнер bitset" - ничего мне не дало.
0
GbaLog-
Любитель чаепитий
3167 / 1473 / 465
Регистрация: 24.08.2014
Сообщений: 5,210
Записей в блоге: 1
Завершенные тесты: 2
10.02.2016, 17:51 4
Цитата Сообщение от Sabnik18 Посмотреть сообщение
Дошел в книге Стенли до битовых операций
Там, разве, не приводятся примеры?
0
sab1ch
BrainOverflow
124 / 128 / 63
Регистрация: 31.03.2013
Сообщений: 556
10.02.2016, 17:53  [ТС] 5
makfak, примеры есть, но все же не все понятно. << >> еще более-менее понятны (сдвиг влево и вправо по битам, как я понял), а логические операторы не понятны. Да и вообще где сейчас и для чего используются битовые операции не ясно.
0
DavidTs
3 / 3 / 8
Регистрация: 25.11.2015
Сообщений: 127
10.02.2016, 18:01 6
Sabnik18, Когда у тебя работа с нулями и единицами. Используются в низкоуровневых работах. Ну для простого примера операторы битового сдвига могут использоваться для выполнения быстрого умножения и деления целых чисел. Сдвиг влево равносилен умножению на 2, а сдвиг вправо - делению на 2.

Добавлено через 5 минут
Sabnik18, Вот пример логического "И".
11000001
01111111
& ---------------
01000001
Посмотри таблицу булевых функцией. ( 0&0, 0&1=0, 1&0=0, 1&1=1).
0
Ferrari F1
793 / 522 / 156
Регистрация: 27.01.2015
Сообщений: 3,025
Записей в блоге: 1
Завершенные тесты: 1
10.02.2016, 18:03 7
Цитата Сообщение от Sabnik18 Посмотреть сообщение
но никак не могу понять их предназначение.
Ну например битовые операции (в частности, битовый сдвиг (причем сдвигов бывает целая куча видов)) нужны для умножения/деления чисел.
Также битовые операции (в частности, операция xor) широко используются в криптографических целях.

Вобще говоря, я когда только начинал читать литературу по Си++ (или чистому Си), то тоже задавался вопросом о предназначении битовых сдвигов и других операций.
Эта тема манипулирования числами на уровне битов очень хорошо обмусоливается в учебниках по ассемблеру.
1
SergioO
168 / 184 / 90
Регистрация: 13.12.2015
Сообщений: 995
10.02.2016, 18:49 8
Цитата Сообщение от Sabnik18 Посмотреть сообщение
Дошел в книге Стенли до битовых операций, но никак не могу понять их предназначение
байт = 8 бит. 00000001 - значит включить одну из 8 ламп. 10011000 - значит 3 лампы будут светиться и тд, те 0 или 1 означает включена лампа или нет. (реальное устройство) теперь выключите старшую лампу (00011000), затем зажгите младшую (00011001). вот вам и битовые операции.
1
sab1ch
BrainOverflow
124 / 128 / 63
Регистрация: 31.03.2013
Сообщений: 556
10.02.2016, 19:06  [ТС] 9
DavidTs, это типа как сложение двоичных кодов?

Добавлено через 29 секунд
Ferrari F1, если вначале не понимал для чего нужны битовые операции, потом все равно же как-то понял. Как?
0
Ferrari F1
793 / 522 / 156
Регистрация: 27.01.2015
Сообщений: 3,025
Записей в блоге: 1
Завершенные тесты: 1
10.02.2016, 20:34 10
Sabnik18, понимать, для чего нужны битовые операции - это одно, а найти для них уместное применение в своем коде - это совсем другое.
Если писать код на Си++, про битовые операции можно вобщем-то забыть.
0
castaway
Эксперт С++
4934 / 3039 / 455
Регистрация: 10.11.2010
Сообщений: 11,119
Записей в блоге: 10
Завершенные тесты: 1
10.02.2016, 20:53 11
Цитата Сообщение от Sabnik18 Посмотреть сообщение
Для чего нужны битовые операции?
Очевидно же, для работы с битами.
0
_Ivana
3236 / 1864 / 235
Регистрация: 01.03.2013
Сообщений: 5,108
Записей в блоге: 5
10.02.2016, 23:27 12
Если у тебя спрошено будет: что полезнее, солнце или месяц? — ответствуй: месяц. Ибо солнце светит днём, когда и без того светло; а месяц — ночью.
Не нужны короче ни битовые операции, ни солнце. И так светло.
0
IGPIGP
Комп_Оратор)
Эксперт по математике/физике
7089 / 3392 / 460
Регистрация: 04.12.2011
Сообщений: 9,438
Записей в блоге: 5
11.02.2016, 01:25 13
Sabnik18, представьте, что Вы судья на матче по гольфу. Решающая подача, стадион замер... и на поле громыхая и поскрипывая выползает микросхемища. В каждой ноге по бите. Если не установить биты нижних ног в правильное положение, то она начнёт всё крошить в капусту. Начнётся хаос.
0
hoggy
Заблокирован
Эксперт С++
11.02.2016, 02:14 14
Цитата Сообщение от Sabnik18 Посмотреть сообщение
Где вообще они используются и как с ними работать? Объясните, если это возможно, на простых примерах.
наиболее распространенное применение - флаги операций.

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

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

как можно было реализовать такое?

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

C++
1
2
3
4
bool read;
bool write;
bool append;
bool no_create;
и тд.
если true, значит настройка активирована. false - выключена.

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

кроме того, как задавать все эти режимы работы?
заводить отдельный метод на каждый флажок что ли?

есть более экономичный и удобный способ - закодировать флаги в виде битов.

бит выключен - значит режим отключен.
бит включен - режим активирован.

в одну 32 битную интовую переменную влезет до 32 различных флагов включительно.
просто представьте себе сколько булевых переменных может сэкономить одна интовая.

и работать с ними удобно:

C++
1
window wnd(FULLSCREEN|MODAL|SHOW|DOUBLE_BUFFER);
можно указывать сразу пачку флажков через символ "палка".

деактивировать сразу пачками.

проверять по нескольку флажков за раз.

и тп.

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

по этой причине, битовые операции получили широчайшее распространение
в области разработки "машин состояний".
4
GbaLog-
Любитель чаепитий
3167 / 1473 / 465
Регистрация: 24.08.2014
Сообщений: 5,210
Записей в блоге: 1
Завершенные тесты: 2
12.02.2016, 14:57 15
hoggy, Что-то я подобное в исходниках Doom'a видел и во втором необязательном аргументе fstream, можете простейший пример привести, как их после передачи в функцию обработать?
0
Ferrari F1
793 / 522 / 156
Регистрация: 27.01.2015
Сообщений: 3,025
Записей в блоге: 1
Завершенные тесты: 1
12.02.2016, 18:05 16
makfak, как вариант, делать ассемблерные вставки
0
hoggy
Заблокирован
Эксперт С++
12.02.2016, 18:37 17
Цитата Сообщение от makfak Посмотреть сообщение
простейший пример привести, как их после передачи в функцию обработать
http://rextester.com/BBXJX64960

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#include <iostream>
 
struct window
{
    enum sMODE{ 
        eFULL_SCREEN   = 1<<1,
        eDOUBLE_BUFFER = 1<<4,
        eMODAL         = 1<<2,
        eSHOW          = 1<<3,
    };
    
    
    window(const int flags):m_flags(flags){}
 
 
    void about_me()const
    {
        if( has_(eFULL_SCREEN)  )
            std::cout<<"полноэкранный режим активирован\n";
        if( has_(eDOUBLE_BUFFER)  )
            std::cout<<"двойная буферизация активирована\n";
        if( has_(eMODAL)  )
            std::cout<<"модальный режим активирован\n";
        if( has_(eSHOW)  )
            std::cout<<"статус: отображается на экране\n";
        
        std::cout<<"=========================\n\n";
    }
    
    void unset(const int flags)
    { 
        // убрать флаги
        m_flags &= (~flags); 
    }
    
    void show()
    {
        // добавить флаг
        m_flags |= eSHOW; 
    }
    
    void hide()
    {
        // убрать флаг
        m_flags &= (~eSHOW); 
    }
    
private:
    int m_flags;
    
    
    
    
    // true, если все указанные флаги включены
    bool has_(const int flags)const
    {
        return (flags & m_flags) == flags;
    }
};
 
 
 
int main()
{
    std::cout << "Hello, world!\n";
    
    typedef window
        MODE;
    
    
    
    window wnd(MODE::eFULL_SCREEN|MODE::eDOUBLE_BUFFER|MODE::eMODAL);
    wnd.about_me();
    
    wnd.show();
    wnd.about_me();
    
    wnd.unset(MODE::eDOUBLE_BUFFER);
    wnd.about_me();
    
    wnd.unset(MODE::eFULL_SCREEN);
    wnd.hide();
    wnd.about_me();
    
}
так же, у меня есть класс для высокоуровневой работы с битовыми флагами:


C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
// flag.h
// подарок от hoggy
 
#pragma once
 
namespace tools
{
    template<class ENUMERATION_TYPE, class INTEGRAL_TYPE = int>
    class flag
    {
    public:
        typedef ENUMERATION_TYPE ENUMERATION;
        typedef INTEGRAL_TYPE INTEGRAL;
 
        explicit flag(const INTEGRAL starflag = 0 );
        explicit flag(const ENUMERATION starflag);
        explicit flag(const bool, const ENUMERATION starflag);
        explicit flag(const bool, const INTEGRAL starflag);
 
        const flag& operator=(const INTEGRAL fl);
        const flag& operator=(const ENUMERATION fl);
 
        static const flag& castFrom(const INTEGRAL& src);
        static flag& castFrom(INTEGRAL& src);
 
        static const ENUMERATION& cast(const INTEGRAL& src);
        static const INTEGRAL& cast(const ENUMERATION& src);
        static ENUMERATION& cast(INTEGRAL& src);
        static INTEGRAL& cast(ENUMERATION& src);
 
        bool empty()const { return cast(m_flags)==0; }
        void clear()      { cast(m_flags)=0; } 
        void full()       { cast(m_flags)=1; } 
 
        const ENUMERATION& getByEnumeration()const { return m_flags;  } 
        ENUMERATION& getByEnumeration()            { return m_flags;  } 
 
        const INTEGRAL& getByIntegral()const  { return cast(m_flags);  } 
        INTEGRAL& getByIntegral()             { return cast(m_flags);  } 
 
        //true, если все указанные флаги включены: флаг1|флаг2|флаг3
        bool has(const ENUMERATION fl)const { return (cast(fl) & cast(m_flags)) == cast(fl); } 
        bool has(const INTEGRAL fl)const    { return (fl & cast(m_flags)) == fl; } 
 
        //true, если хотя бы один из указанных флагов включен: флаг1|флаг2|флаг3
        bool hasAny(const ENUMERATION fl)const { return (cast(fl) & cast(m_flags)) != 0; } 
        bool hasAny(const INTEGRAL fl)const    { return (fl & cast(m_flags)) != 0; } 
 
        //true, если this содержит флаги идентичные указанным
        bool hasOnly(const ENUMERATION fl)const { return operator==(flag(fl)); }
        bool hasOnly(const INTEGRAL fl)const    { return operator==(flag(fl)); }
 
        //установить флаги: флаг1|флаг2|флаг3
        void set(const ENUMERATION fl)  { m_flags       = fl; } 
        void set(const INTEGRAL fl)     { cast(m_flags) = fl; } 
 
        //если success true, тогда добавить флаги: флаг1|флаг2|флаг3
        void add(const bool success, const ENUMERATION fl);
        void add(const bool success, const INTEGRAL fl);
 
        //добавить флаги: флаг1|флаг2|флаг3
        void add(const ENUMERATION fl)  { cast(m_flags) |= fl; } 
        void add(const INTEGRAL fl)     { cast(m_flags) |= fl; } 
 
        //удалить флаги: флаг1|флаг2|флаг3
        void del(const ENUMERATION fl)  { cast(m_flags) &= (~fl); } 
        void del(const INTEGRAL fl)     { cast(m_flags) &= (~fl); } 
 
        //если enable, добавить флаги: флаг1|флаг2|флаг3
        //а иначе - выключить
        void enable(const bool enable, const ENUMERATION fl);
        void enable(const bool enable, const INTEGRAL fl);
 
        // выключает флаги oldFlag, и вкючает флаги newFlag
        template<class Old, class New>
        void change(const Old oldFlag, const New newFlag);
 
        //сделать включенными только флаги: флаг1|флаг2|флаг3
        void only(const ENUMERATION fl) { clear(); add(fl); }
        void only(const INTEGRAL fl)    { clear(); add(fl); }
 
        //из включенных флагов оставить только указанные флаги: флаг1|флаг2|флаг3
        void validOnly(const ENUMERATION fl ){ cast(m_flags) &= fl; } 
        void validOnly(const INTEGRAL fl )   { cast(m_flags) &= fl; } 
 
        // true, если хотя бы один выставлен
        operator bool()const { return !empty(); }
 
        //true, если флаги идентичны
        bool operator==(const flag fl)const { return m_flags==fl.m_flags; }
 
        //true, если флаги не идентичны
        bool operator!=(const flag fl)const { return m_flags!=fl.m_flags; }
    private:
        ENUMERATION m_flags;
    };
 
    #define dTEMPLATE \
        template<class ENUMERATION, class INTEGRAL>
    #define dCLASS \
        flag<ENUMERATION, INTEGRAL>
 
    dTEMPLATE dCLASS::flag(const INTEGRAL starflag)
        :m_flags(cast(starflag))
    {}
 
    dTEMPLATE dCLASS::flag(const ENUMERATION starflag)
        :m_flags(starflag)
    {}
 
    dTEMPLATE dCLASS::flag(const bool is_true, const ENUMERATION starflag)
        :m_flags( is_true? starflag: ENUMERATION(0) )
    {}
 
    dTEMPLATE dCLASS::flag(const bool is_true, const INTEGRAL starflag)
        :m_flags( is_true? cast(starflag): ENUMERATION(0) )
    {}
 
    dTEMPLATE const dCLASS& dCLASS::operator=(const INTEGRAL fl)
        { set(fl); return *this; }
 
    dTEMPLATE const dCLASS& dCLASS::operator=(const ENUMERATION fl)
        { set(fl); return *this; }
 
    dTEMPLATE
    const dCLASS& dCLASS::castFrom(const INTEGRAL& src)
    {
        const flag* ptr = reinterpret_cast<const flag*>(&src);
        return *ptr; 
    }
 
    dTEMPLATE 
    dCLASS& dCLASS::castFrom(INTEGRAL& src)
    {
        flag* ptr = reinterpret_cast<flag*>(&src);
        return *ptr; 
    }
 
    dTEMPLATE const ENUMERATION& dCLASS::cast(const INTEGRAL& src)
    {
        const ENUMERATION* ptr = reinterpret_cast<const ENUMERATION*>(&src);
        return *ptr;
    }
 
    dTEMPLATE ENUMERATION& dCLASS::cast(INTEGRAL& src)
    {
        ENUMERATION* ptr = reinterpret_cast<ENUMERATION*>(&src);
        return *ptr;
    }
 
    dTEMPLATE const INTEGRAL& dCLASS::cast(const ENUMERATION& src)
    {
        const INTEGRAL* ptr = reinterpret_cast<const INTEGRAL*>(&src);
        return *ptr;
    }
 
    dTEMPLATE INTEGRAL& dCLASS::cast(ENUMERATION& src)
    {
        INTEGRAL* ptr = reinterpret_cast<INTEGRAL*>(&src);
        return *ptr;
    }
 
    dTEMPLATE void dCLASS::add(const bool success, const ENUMERATION fl)  
    {
        if(success)
            add(fl);
    }
 
    dTEMPLATE void dCLASS::add(const bool success, const INTEGRAL fl)  
    {
        if(success)
            add(fl);
    } 
 
    dTEMPLATE void dCLASS::enable(const bool enable, const ENUMERATION fl)
    {
        enable? this->add(fl) : this->del(fl);
    }
    dTEMPLATE void dCLASS::enable(const bool enable, const INTEGRAL fl)
    {
        enable? this->add(fl) : this->del(fl);
    }
 
    dTEMPLATE
    template<class Old, class New>
    void dCLASS::change(const Old oldFlag, const New newFlag)
    {
        this->del(oldFlag);
        this->add(newFlag);
    }
 
    #undef dTEMPLATE
    #undef dCLASS
 
}//namespace tools
 
 
#if 0
//ИСПОЛЬЗОВАНИЕ:
 
enum eFLAGS { eNONE = 0, eONE = 1<<1, eTWO = 1<<2, eTHREE = 1<<3 };
typedef tools::flag<eFLAGS> flag_t;
 
flag_t f(eONE|eTWO);
EXPECT_EQ(eONE|eTWO,    f.getByEnumeration()    );
EXPECT_EQ(false,        f.empty()               );
EXPECT_EQ(true,        (f)? true: false         );
EXPECT_EQ(true,         f.has(eONE)             );
EXPECT_EQ(true,         f.has(eONE|eTWO)        );
EXPECT_EQ(false,        f.has(eONE|eTWO|eTHREE) );
EXPECT_EQ(true,         f.hasAny(eONE|eTWO)     );
EXPECT_EQ(true,         f.hasAny(eTWO|eTHREE)   );
EXPECT_EQ(false,        f.hasonly(eONE)         );
EXPECT_EQ(true,         f.hasonly(eONE|eTWO)    );
 
f.validOnly(eONE);
           
EXPECT_EQ(eONE,   f.getByEnumeration()  );
EXPECT_EQ(false,  f.empty()             );
EXPECT_EQ(true,  (f)? true: false       );
EXPECT_EQ(true,   f.has(eONE)           );
EXPECT_EQ(false,  f.has(eONE|eTWO)      );
EXPECT_EQ(true,   f.hasAny(eONE|eTWO)   );
EXPECT_EQ(false,  f.hasAny(eTWO|eTHREE) );
EXPECT_EQ(true,   f.hasonly(eONE)       );
EXPECT_EQ(false,  f.hasonly(eONE|eTWO)  );
#endif
1
GbaLog-
Любитель чаепитий
3167 / 1473 / 465
Регистрация: 24.08.2014
Сообщений: 5,210
Записей в блоге: 1
Завершенные тесты: 2
12.02.2016, 19:37 18
hoggy, Что за функция EXPECT_EQ?
0
hoggy
Заблокирован
Эксперт С++
12.02.2016, 19:43 19
Цитата Сообщение от makfak Посмотреть сообщение
Что за функция EXPECT_EQ?
это - макрос из фреймворка для тестирования gtest

"ожидаю эквивалент".

первый аргумент - что ожидается
второй - что имеем по факту.

если будут расхождения,
тесты это покажут.
0
GbaLog-
Любитель чаепитий
3167 / 1473 / 465
Регистрация: 24.08.2014
Сообщений: 5,210
Записей в блоге: 1
Завершенные тесты: 2
12.02.2016, 19:47 20
hoggy, И в каком фреймворке этот макрос имеется?
0
12.02.2016, 19:47
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
12.02.2016, 19:47

Для чего нужны указатели?
Кто может объяснить для чего нужны указатели и смысл их? в интернете одна муть...

Для чего нужны интерфейсы?
Объясните на пальцах для чего нужны интерфейсы, как я понял они описывают...

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


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru