Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > Побитовые операции


Автор: student0511 1.10.2006, 17:25
ALL
Здрасти всем!  smile 
   Наткнулся на задачу с множествами, где необходимо использовать побитовые операциии. До этого с данной темой не сталкивался. Подскажите, pls, где можно найти исчерпывающую информацию, а то в google ничего путёвого не нашёл. Мне не понятны некоторые моменты; вот, на пример:
 
Код

 ...z>>1 & 0x00000080)<<8;
 

или
  
Код

  ....(z>>1) & 0xffff7fff ) )&0x0000ff00); 
  

Что такое 0x00000080, 0xffff7fff, 0x0000ff00 ? Операции ">>" и "<<" и др. лог. операции мне чуток ясны, а вот какую роль играют, если я не ошибаюсь, маски(так их называют вроде) я нигде не нашёл. Как задаются или они явл. константными выражениями. Объясните, плз!  smile Или можно примеры простенькие, если не трудно.

Автор: MAKCim 1.10.2006, 17:41
Цитата

а вот какую роль играют, если я не ошибаюсь, маски(так их называют вроде) я нигде не нашёл. Как задаются или они явл. константными выражениями. Объясните, плз!  

Ну допустим есть число 10001001 01110100 (типа short)
Код

...
short i = 37236;
...

Чтобы проверить установлен ли 3 бит (нумерация с нуля)
используем логическое умножение на маску 00000000 00001000 или
Код

...
short j  = 1<<3;
if (i & j);  // бит установлен
else; // нет

Это совйство связано с таблицей истинности для лог. умножения, т. е
0 & 0 = 0
0 & 1 = 1 & 0 = 0
1 & 1 = 1
т. е
10001001 01110100
&
00000000 00001000
=
00000000 00000000 = 0

Автор: bsa 1.10.2006, 17:45
Базовые понятия Си:

0x... - означает, что число в шестнадцатиричной системе. Например, 0x10 (это 16 в десятичной)
0... - означает, что число в восьмиричной системе. Например, 017 (это 15 в десятичной)

Маской называют число, которое позволяет выделить некую часть из другого. Маски логично задавать в двоичной системе. Но Си это не позволяет, поэтому используют 16-ти ричную систему.
Пример. Есть строка, состоящая из цифр 0, 1... 9. Хотелось бы превратить это в массив чисел от 0, до 9. В ASCII символы '0'...'9' задаются кодами 0x30...0x39. Поэтому, если применить маску 0x0F, то она уберет ненужную информацию и из 0x39 получится 0x09. Это выглядит так: 0x39 & 0x0F = 0x09. Здесь - & - подитовая операция AND. Есть еще | - OR, и ^ - XOR.

>> и << - это операции побитового сдвига вправо и влево соответственно. Сдвиг влево на n разрядов эквивалентен умножению на 2 в степени n, а сдвиг вправо - делению. Данные операции применяются только к целым типам.

Автор: student0511 1.10.2006, 18:15
А маски составляются в процессе создания программы, или они являются постоянными и применяются в определённых ситуациях? И, если первое, то  можно более подробнее объяснить о их свойствах (если так можно выразиться  smile  ). Какие классические задачи существуют с применением побитовых операций?

Автор: MAKCim 1.10.2006, 19:54
Цитата

Какие классические задачи существуют с применением побитовых операций?

Например обнуление переменной
Код

xor AX, AX

Инвертирование бит в числе
Код

x^=~0;

Установка n-го бита
Код

x|=(1<<n);

Сбрасывание n-го бита
Код

x&=(((~0)<<n) | ((~((~0)<<n))>>1));


Автор: likehood 1.10.2006, 22:56
Цитата(MAKCim @  1.10.2006,  20:54 Найти цитируемый пост)
Сбрасывание n-го бита

код C++    
1:    
x&=(((~0)<<n) | ((~((~0)<<n))>>1));


а разве так нельзя:
Код

x &= ~(1<<n);

Автор: student0511 2.10.2006, 01:28
А что же на счёт масок? В каких случаях их применять?  smile 

Автор: Romikgy 2.10.2006, 09:04
Цитата(student0511 @  2.10.2006,  00:28 Найти цитируемый пост)
А что же на счёт масок? В каких случаях их применять? 

когда надо ! зависит от задач

Автор: kondr 2.10.2006, 09:48
Цитата

Какие классические задачи существуют с применением побитовых операций?


Код

int a = 1;
int b = 2;
                
a^=b;
b^=a;
a^=b;


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

Автор: smalcom 2.10.2006, 10:16
при морщинах

Автор: MAKCim 2.10.2006, 14:39
Цитата

а разве так нельзя:

можно  smile 

Автор: student0511 2.10.2006, 15:57
А не подскажите всё-таки ссылочку на данную тему. И про маски можно по-подробнее раскрыть тему  smile  . 

Автор: smalcom 2.10.2006, 20:32
маски это как язык програмирования - млм ты знаешь куда их приткнуть или оно тебе не надо. Придет время возникнет задача и ты поймешь зачем нужны маски. На пальцах тебе не объяснишь и понятно что гугл те ниче не выдал - маски это не раздел програмирования это инструмент это как знание языка и владение им этому нельзя научить. Засим откланиваюся

Автор: student0511 3.10.2006, 00:02
У меня сейчас возникла задача! И я хочу сам допереть до её решения, но т.к., ничего не ведая на данную тему, я  не знаю с чего начать. Тем более по побитовым операциям мало инфы.

Автор: smalcom 3.10.2006, 09:44
ну вот тебе примерчик

Код

unsigned char lpin = ...;//получаем в переменную допустим тошо на ножках LPT порта

if(lpin & 0x01) ...;//если 0-я ножка не ноль
if(lpin & 0x02) ...;//если 1-я ножка не ноль
...
if(lpin & 0x80) ...;//если 7-я ножка не ноль
/*а теперь хочу скинуть в ноль 5-ю ножку и установить в единицу вторую а остальные не
трогать*/
unsigned char temp_lpin = lpin;
temp_lpin &= 0xDF;//1101 1111 - сбрасываем пятую
temp_lpin |= 0x04;//0000 0100 - ставим вторую


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

Автор: student0511 3.10.2006, 19:20
 мне свой порт и я расскажу какой ты бит 

Гы-гы. Сильно cказано  smile 
 Можно любое число брать, я про 0xDF, чтобы только получался необходимый результат, т.е. в данном случае: на пятой позиции в 2-ой системе стоял 0-ой бит. Ясно.

Автор: student0511 3.10.2006, 20:16
А если у меня положение, на которое нужно поставить 1, меняется и зависит от чего-либо. Ну, на пример, у меня есть слово. Как мне поставить единицы на те номера, которые соответствуют номеру буквы в алфавите?  smile 
Вроде допёр: просто взять переменную long из одной 1 единичке и нулей. Потом сдвигать 1 на то место, которое соответствует номеру буквы и применять операцию "ИЛИ". А изначатльные переменные взять за нули.  Можно же так?

Автор: MAKCim 3.10.2006, 21:16
student0511
Если брать глобально маски в UNIX очень часто используются
(и в API, и в ядре), потому как они позволяют (точнее не они, а с помощью их) очень эффективно передавать флаги для указания включения чего-нибудь куда-нибудь. Сам подумай, unsigned long для большинства 32-х разрядных платформ способен хранить 64 разных флага! А с помощью масок можно легко проверять установку определенного бита, а вместе с тем флага

Автор: student0511 3.10.2006, 22:20
 Т.е. 64 - это 8 байт чтоль? Значит весь алфавит можно забить, даже останется  smile 

Автор: Earnest 4.10.2006, 07:12
Цитата(MAKCim @  3.10.2006,  22:16 Найти цитируемый пост)
 unsigned long для большинства 32-х разрядных платформ способен хранить 64 разных флага!

Все-таки 32. ULONG  на 32-разрядной платформе обычно 4 байта.

Автор: MAKCim 4.10.2006, 08:40
Цитата

Все-таки 32. ULONG  на 32-разрядной платформе обычно 4 байта.

ну да, спасибо за поправку

Автор: student0511 8.10.2006, 00:36
    Всё. Разобрался. Даже что-то написал  smile  . Спасибо за объяснения!   smile 
    А вообще задача стояла следующим образом: продемонстрировать, используя "машинное слово", работу со множествами.   
Кому интересно:

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)