У реальному світі випадки використання побітових операторів [закрито]


224

Які є випадки використання реального світу наступних побітових операторів?

  • І
  • XOR
  • НЕ
  • АБО
  • Зсув вліво / вправо

1
Я пам'ятаю, коли я вперше дізнався про них, здавалося, що вони використовуються лише для низького рівня c ... але з тих пір вони входили в панель інструментів, і я їх часто використовую, в тому числі під час програмування "високого рівня". Вони зараз як + і * для мене.
Дуб

2
@Anon. На мій погляд, реальний світ мав означати що-небудь, крім програмування низького рівня, що є найбільш очевидним використанням бітових операторів.
Олів'є Лалонде



Можна також використовувати двійковий XOR, щоб знайти пропущене число в перестановці: martinkysel.com/codility-permmissingelem-solution
Janac Meena

Відповіді:


216
  • Поля бітів (прапори)
    Вони є найефективнішим способом представлення того, стан якого визначається декількома властивостями "так чи ні". ACL - хороший приклад; якщо ви скажімо 4 дискретних дозволу (читати, записувати, виконувати, змінювати політику), краще зберігати це в 1 байті, а не відходах 4. Вони можуть бути відображені на типи перерахування на багатьох мовах для додаткової зручності.

  • Комунікація через порти / сокети
    Завжди включає контрольні суми, парність, стоп-біти, алгоритми управління потоком тощо, які зазвичай залежать від логічних значень окремих байтів на відміну від числових значень, оскільки носій може бути здатний передавати лише один біт на Час.

  • Стиснення, шифрування
    Обидва вони сильно залежать від бітових алгоритмів. Подивіться на приклад алгоритм дефляції - все в бітах, а не в байтах.

  • Машини з кінцевим
    станом, я кажу в основному про тип, вбудований в якийсь апарат, хоча вони можуть бути знайдені і в програмному забезпеченні. Це комбінаторний характер - вони можуть буквально отримувати «скомпільований» вниз на купу логічних вентилів, тому вони повинні бути виражені як AND, OR, NOTі т.д.

  • Графіка Тут навряд чи достатньо місця, щоб потрапити в кожну область, де ці оператори використовуються в графічному програмуванні. XOR(або ^) тут особливо цікаво, оскільки застосування одного і того ж вводу вдруге скасує перший. Старі графічні інтерфейси використовували для цього посилання на виділення виділень та інші накладки, щоб усунути необхідність у дорогому перемальовуванні. Вони все ще корисні у повільних графічних протоколах (тобто віддаленому робочому столі).

Це були лише перші кілька прикладів, які я придумав - це навряд чи вичерпний список.


Привіт @Aaronaught! Ви дійсно поділилися з нами дуже добрими знаннями. Мені цікаво дізнатися більше про випадки реального світу оператора Bitwise. Ви б не хотіли поділитися своєю довідкою з нами, було б дуже корисно прочитати про це докладніше.
Хена Хуссей

Чи корисні побізні операції для обчислень, що регулюються?
Аарон Франке

47

Це дивно?

(value & 0x1) > 0

Це ділиться на два (парні)?

(value & 0x1) == 0

3
Залежно від мовного значення & 0x1> 0 може бути проаналізовано як значення & (0x1> 0)
leeeroy

3
@leeeroy - Досить правда. Додано кілька паренів.
Сет

Сучасні оптимізатори автоматично перетворять вирази типу (значення% 2)! = 0 у вказані вище вирази. godbolt.org/z/mYEBH4
Феррарезі

26

Ось деякі поширені ідіоми, що стосуються прапорів, що зберігаються як окремі біти.

enum CDRIndicators {
  Local = 1 << 0,
  External = 1 << 1,
  CallerIDMissing = 1 << 2,
  Chargeable = 1 << 3
};

unsigned int flags = 0;

Встановіть прапор, що підлягає сплаті:

flags |= Chargeable;

Очистити прапор CallerIDМіссінг:

flags &= ~CallerIDMissing;

Перевірте, чи встановлено CallerIDMissing та Chargeable:

if((flags & (CallerIDMissing | Chargeable )) == (CallerIDMissing | Chargeable)) {

}

25

Я використовував побітні операції при впровадженні моделі безпеки для CMS. Він мав сторінки, до яких користувачі могли отримати доступ, якщо вони були у відповідних групах. Користувач може бути у кількох групах, тому нам потрібно було перевірити, чи не було перетину між групами користувачів та групами сторінок. Тому ми призначили кожній групі унікальний ідентифікатор потужності-2, наприклад:

Group A = 1 --> 00000001
Group B = 2 --> 00000010
Group C = 3 --> 00000100

Ми АБО ці значення разом і зберігаємо значення (як єдине ціле) зі сторінкою. Наприклад, якщо до сторінки можна отримати доступ групами A&B, ми зберігаємо значення 3 (яке у двійковій формі є 00000011) як контроль доступу до сторінок. Таким же чином ми зберігаємо значення ідентифікаторів групи ORed з користувачем, щоб представити, в яких групах вони перебувають.

Отже, щоб перевірити, чи може певний користувач отримати доступ до певної сторінки, вам потрібно просто разом зіставити значення І і перевірити, чи значення не дорівнює нулю. Це дуже швидко, оскільки ця перевірка реалізована в одній інструкції, без циклу, без обходу баз даних.


24

Хороший приклад - програмування низького рівня. Наприклад, вам може знадобитися записати певний біт в регістр, нанесений на пам'ять, щоб змусити частину обладнання зробити те, що вам потрібно:

volatile uint32_t *register = (volatile uint32_t *)0x87000000;
uint32_t          value;
uint32_t          set_bit   = 0x00010000;
uint32_t          clear_bit = 0x00001000;

value = *register;            // get current value from the register
value = value & ~clear_bit;   // clear a bit
value = value | set_bit;      // set a bit
*register = value;            // write it back to the register

Крім того , htonl()і htons()реалізуються з використанням &і |операторів (на машинах , у яких порядок байт (Byte замовлення) не відповідає мережевий замовлення):

#define htons(a) ((((a) & 0xff00) >> 8) | \
                  (((a) & 0x00ff) << 8))

#define htonl(a) ((((a) & 0xff000000) >> 24) | \
                  (((a) & 0x00ff0000) >>  8) | \
                  (((a) & 0x0000ff00) <<  8) | \
                  (((a) & 0x000000ff) << 24))

7
Не всі говорять машинно. Що твій другий приклад робиш?
ChaosPandion

7
htons()і htonl()є функціями POSIX для заміни a shortабо a longз hнестабільності хоста ( ) на порядок байтів мережі ( n).
Карл Норум

Ви можете використовувати аналогічний метод, щоб зробити біт-реверс в операціях O (logN).
Майк Десімоне

LOL, коли я вперше побачив це, я подумав, що це збірка!
0x499602D2

Чи не htonl()для 32-бітного intзначення? longозначає 64-бітові багато мов.
Аарон Франке

21

Наприклад, я використовую їх для отримання значень RGB (A) від упакованих кольорових кольорів.


І це робиться дуже швидко!
Callum Rogers

У C # - це один із тих випадків, коли це справді найкраще рішення, для зручності читання та швидкості.
КапітанКейсі

4
На моїй машині (a & b) >> cбільш ніж у 5 разів швидше, ніж a % d / e(обидва способи витягти єдине значення кольору з int, що представляє ARGB). Відповідно, 6,7 та 35,2 за 1 мільярд ітерацій.
Бенджі XVI

@BenjiXVI C # має оптимізацію компілятора для цього. Причина, за якою ви спостерігаєте різницю швидкостей, полягає в тому, що в C # %не є оператором Modulus, це оператором Залишком. Вони еквівалентні позитивним значенням, але відрізняються від негативних. Якщо ви надаєте відповідні обмеження (передаючи а uintзамість, intнаприклад), то два приклади повинні мати однакову швидкість.
Аарон Франке

вибачте, я знаю, що минуло давно. Чи можете ви, будь ласка, показати приклад того, як їх використовувати для отримання кожного значення RGB?
Jinx

14

Коли у мене є купа булевих прапорів, я люблю зберігати їх у int.

Я виймаю їх, використовуючи побіто-І. Наприклад:

int flags;
if (flags & 0x10) {
  // Turn this feature on.
}

if (flags & 0x08) {
  // Turn a second feature on.
}

тощо.


23
Сподіваємось, це фактично константи у вашому реальному коді, а не у магічних числах :)
Earlz

1
Одним із прикладів використання булевих прапорів у світі низького рівня є вміст із різними платформами GUI. Наприклад, ви можете використовувати my_button.Style | = STYLE_DISABLED, щоб вимкнути його.
MauriceL

1
Я знаю, що ця тема є агностичною мовою, але C пропонує простий спосіб зробити це за допомогою бітових полів, щоб ви могли використовувати такі речі if (flags.feature_one_is_one) { // turn on feature }. Це в стандарті ANSI C, тому портативність не повинна бути проблемою.
polandeer

було б непогано отримати пояснення, що робить цей фрагмент коду, чому прапори не ініціалізуються, що ви маєте на увазі під "зберігати їх усіх в
інті

12

& = І:
маскуйте конкретні біти.
Ви визначаєте конкретні біти, які слід відображати чи не відображати. 0x0 & x очистить всі біти в байті, тоді як 0xFF не змінить x. 0x0F відобразить біти в нижній області.

Перетворення:
Для передачі більш коротких змінних у більш довгі з бітовою ідентичністю слід відрегулювати біти, оскільки -1 в інті 0xFFFFFFFF, тоді як -1 в довгому 0xFFFFFFFFFFFFFFFFFF. Для збереження ідентичності ви застосовуєте маску після перетворення.

| = АБО
Встановити біти. Біти будуть встановлені самостійно, якщо вони вже встановлені. У багатьох структурах даних (бітових полях) є прапори, такі як IS_HSET = 0, IS_VSET = 1, які можна встановити самостійно. Щоб встановити прапори, ви застосуєте IS_HSET | IS_VSET (В монтажі C і це дуже зручно читати)

^ = XOR
Знайдіть біти, однакові чи різні.

~ = НЕ
фліп біт.

Можна показати, що всі можливі локальні бітові операції можуть бути реалізовані цими операціями. Отже, якщо вам подобається, ви можете реалізувати інструкцію ADD виключно за допомогою бітових операцій.

Деякі чудові хаки:

http://www.ugcs.caltech.edu/~wnoise/base2.html
http://www.jjj.de/bitwizardry/bitwizardrypage.html


Нижче наведено посилання, яке дає прекрасні приклади використання побітових операторів в AS3 для надшвидких математичних операцій (але це, ймовірно, може бути застосовано до більшості мов): lab.polygonal.de/2007/05/10/bitwise-gems-fast- ціла математика
сильно залучалася

Я думаю, що "НЕ" має бути = ~, ні |=, що АБО.
Майк Десимоне

Для & = AND- Чому я хотів би очистити всі біти, чому я хочу отримати немодифіковану версію байта, і що мені робити з нижньою нибл?
заплутався00

1
@ confused00 right, швидший / простіший спосіб звести нанівець результат - xorце сам по собі. Я можу подумати про чимало причин, з яких ви можете витягнути нижню жилку. Особливо, якщо цей нижній нібіл є частиною структури даних, і ви хочете використовувати його як маску або ORіншу структуру.
Джеймс М. Лежав

11

Шифрування - це все побітові операції.


4
Дійсно? Реалізація шифрування, ймовірно, використовує побітові операційні можливості, але алгоритми шифрування зазвичай описуються числовими термінами, а не з точки зору представлення бітів.
Костянтин

1
То що ви робите з іншими алгоритмами, ніж їх реалізовувати? Мені цікаво.
рекурсивна

2
@Constantin: Дивіться, наприклад, опис того, як реалізується DES: ( en.wikipedia.org/wiki/…
Wayne Conrad

1
@recursive, Якщо ви запитаєте про мене особисто - я не розробляю криптографічні алгоритми і не реалізую їх. Але люди роблять багато речей, як аналіз їх теоретичних слабкостей.
Костянтин

@Constantin: погляньте на це, це лише один приклад серед багатьох, як зазвичай описуються криптографічні алгоритми (частина): en.wikipedia.org/wiki/Substitution_box
SyntaxT3rr0r

9

Ви можете використовувати їх як швидкий і брудний спосіб хеш-даних.

int a = 1230123;
int b = 1234555;
int c = 5865683;
int hash = a ^ b ^ c;

8

Я щойно використав побіт-XOR ( ^) близько трьох хвилин тому для обчислення контрольної суми для послідовного зв'язку з PLC ...


7

Побітове & використовується для маскування / вилучення певної частини байта.

1 байт змінна

 01110010
&00001111 Bitmask of 0x0F to find out the lower nibble
 --------
 00000010

Особливо для обчислень часто використовують оператор зсуву (<< >>).


6

Це приклад для читання кольорів із растрового зображення у байтовому форматі

byte imagePixel = 0xCCDDEE; /* Image in RRGGBB format R=Red, G=Green, B=Blue */

//To only have red
byte redColour = imagePixel & 0xFF0000; /*Bitmasking with AND operator */

//Now, we only want red colour
redColour = (redColour >> 24) & 0xFF;  /* This now returns a red colour between 0x00 and 0xFF.

Я сподіваюся, що це крихітні приклади допомагають….


5

У абстрагованому світі сучасної сучасної мови не дуже багато. Файл IO - це легкий, який спадає на думку, хоча він виконує побітові операції на вже реалізованому і не реалізує щось, що використовує побітові операції. Однак, як простий приклад, цей код демонструє видалення атрибута лише для читання з файлу (щоб його можна було використовувати з новим FileStream із зазначенням FileMode.Create) у c #:

//Hidden files posses some extra attibutes that make the FileStream throw an exception
//even with FileMode.Create (if exists -> overwrite) so delete it and don't worry about it!
if(File.Exists(targetName))
{
    FileAttributes attributes = File.GetAttributes(targetName);

    if ((attributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly)
        File.SetAttributes(targetName, attributes & (~FileAttributes.ReadOnly));

    File.Delete(targetName);
}

Що стосується спеціальних реалізацій, ось останній приклад: я створив "центр повідомлень" для надсилання захищених повідомлень з однієї установки нашого розповсюдженого додатку на іншу. В основному, він є аналогом електронної пошти в комплекті з Inbox, Outbox, Sent і т. Д., Але він також має гарантовану доставку з квитанціями про зчитування, тому є додаткові папки за межами "Вхідні" та "Надіслані". З цього приводу я мав вимогу загально визначити, що "у папці" Вхідні "або що" у надісланій папці ". З надісланої папки мені потрібно знати, що читати, а що не читати. З того, що є непрочитаним, мені потрібно знати, що отримано, а що - не. Я використовую цю інформацію для створення динаміки, де застереження, яке фільтрує локальний джерело даних та відображає відповідну інформацію.

Ось як складається перерахунок:

    public enum MemoView :int
    {
        InboundMemos = 1,                   //     0000 0001
        InboundMemosForMyOrders = 3,        //     0000 0011
        SentMemosAll = 16,                  //     0001 0000
        SentMemosNotReceived = 48,          //     0011
        SentMemosReceivedNotRead = 80,      //     0101
        SentMemosRead = 144,                //     1001
        Outbox = 272,                       //0001 0001 0000
        OutBoxErrors = 784                  //0011 0001 0000
    }

Ви бачите, що це робить? По anding (&) зі значенням перерахунку "Inbox", InboundMemos, я знаю, що InboundMemosForMyOrders знаходиться у папці "Вхідні".

Ось приведена версія методу, який створює та повертає фільтр, який визначає подання для вибраної в даний час папки:

    private string GetFilterForView(MemoView view, DefaultableBoolean readOnly)
    {
        string filter = string.Empty;
        if((view & MemoView.InboundMemos) == MemoView.InboundMemos)
        {
            filter = "<inbox filter conditions>";

            if((view & MemoView.InboundMemosForMyOrders) == MemoView.InboundMemosForMyOrders)
            {
                filter += "<my memo filter conditions>";
            }
        }
        else if((view & MemoView.SentMemosAll) == MemoView.SentMemosAll)
        {
            //all sent items have originating system = to local
            filter = "<memos leaving current system>";

            if((view & MemoView.Outbox) == MemoView.Outbox)
            {
                ...
            }
            else
            {
                //sent sub folders
                filter += "<all sent items>";

                if((view & MemoView.SentMemosNotReceived) == MemoView.SentMemosNotReceived)
                {
                    if((view & MemoView.SentMemosReceivedNotRead) == MemoView.SentMemosReceivedNotRead)
                    {
                        filter += "<not received and not read conditions>";
                    }
                    else
                        filter += "<received and not read conditions>";
                }
            }
        }

        return filter;
    }

Надзвичайно проста, але акуратна реалізація на рівні абстракції, яка зазвичай не вимагає побітних операцій.


4

Кодування Base64 - приклад. Кодування Base64 використовується для представлення двійкових даних у вигляді символів для друку для надсилання електронної пошти (та інших цілей). Кодування Base64 перетворює серію 8-бітових байтів у 6-бітові індекси пошуку символів. Бітові операції, зсув, і'ing, або 'oring, not'ing дуже корисні для реалізації бітових операцій, необхідних для кодування та декодування Base64.

Це звичайно лише 1 із незліченних прикладів.



4

Зазвичай бітові операції швидше, ніж робити множення / ділення. Отже, якщо вам потрібно помножити змінну x на сказати 9, ви зробите x<<3 + xце на кілька циклів швидше, ніж x*9. Якщо цей код знаходиться в межах ISR, ви заощадите на час відповіді.

Аналогічно, якщо ви хочете використовувати масив у якості кругової черги, було б швидше (і більш елегантніше) обробляти обертання чеків за допомогою трохи розумних операцій. (розмір вашого масиву повинен бути потужністю 2). Наприклад: ви можете використовувати tail = ((tail & MASK) + 1)замість tail = ((tail +1) < size) ? tail+1 : 0, якщо ви хочете вставити / видалити.

Крім того, якщо ви хочете, щоб прапор помилки містив кілька кодів помилок разом, кожен біт може містити окреме значення. Ви можете І з кожним індивідуальним кодом помилки як перевірку. Це використовується в кодах помилок Unix.

Також n-бітова растрова карта може бути дійсно крутою і компактною структурою даних. Якщо ви хочете виділити пул ресурсів розміром n, ми можемо використовувати n-біти для представлення поточного стану.



3

Чи число xє потужністю 2? (Корисно, наприклад, в алгоритмах, де лічильник збільшується, а дію потрібно вжити лише логарифмічну кількість разів)

(x & (x - 1)) == 0

Який найвищий біт цілого числа x? (Це, наприклад, можна знайти мінімальну потужність на 2, що перевищує x)

x |= (x >>  1);
x |= (x >>  2);
x |= (x >>  4);
x |= (x >>  8);
x |= (x >> 16);
return x - (x >>> 1); // ">>>" is unsigned right shift

Який найнижчий 1біт цілого числа x? (Допомагає знайти кількість разів, що ділиться на 2.)

x & -x

Непідписаний правий зсув виконується в C шляхом виведення LHS в неподписаний тип. Ваша остання формула не знаходить найнижчий біт [set], вона перевіряє, чи X є потужністю 2. Щоб знайти найнижчий встановлений біт, зробіть x & -x.
Potatoswatter

Хм, ви праві, я якось замінив x & -x першим фрагментом, thx для редагування
Димитріс Андреу

3

Побітові оператори корисні для циклічних масивів, довжина яких становить 2 сили. Як багато хто згадує, побітові оператори надзвичайно корисні і використовуються у прапорах , графіці , мережах , шифруванні . Мало того, але вони надзвичайно швидкі. Мій особистий фаворит використання в циклі масив без умовними . Припустимо, у вас є масив на основі нуля-індексу (наприклад, індекс першого елемента дорівнює 0), і вам потрібно циклічно його циклічно. Під невизначеним терміном я маю на увазі перехід від першого елемента до останнього і повернення до першого. Одним із способів здійснення цього є:

int[] arr = new int[8];
int i = 0;
while (true) {
    print(arr[i]);
    i = i + 1;
    if (i >= arr.length) 
        i = 0;
}

Це найпростіший підхід, якщо ви хочете уникнути, якщо заява, ви можете використовувати модульний підхід таким чином:

int[] arr = new int[8];
int i = 0;
while (true) {
    print(arr[i]);
    i = i + 1;
    i = i % arr.length;
}

Нижньою стороною цих двох методів є те, що оператор модуля є дорогим, оскільки шукає залишок після цілого поділу. І перший метод запускає оператор if на кожній ітерації. Однак при бітовому операторі, якщо довжина масиву є потужністю 2, ви можете легко генерувати послідовність на зразок 0 .. length - 1, використовуючи &(бітовий та) оператор i & length. Знаючи це, код зверху стає

int[] arr = new int[8];
int i = 0;
while (true){
    print(arr[i]);
    i = i + 1;
    i = i & (arr.length - 1);
}

Ось як це працює. У двійковому форматі кожне число, яке є потужністю 2, віднімається на 1, виражається лише одиницею. Наприклад, 3 у двійковій 11, 7 є 111, 15 є 1111і так далі, ви отримуєте думку. Тепер, що станеться, якщо &будь-яке число проти числа, що складається лише з числа у двійковому? Скажімо, ми робимо це:

num & 7;

Якщо numвона менша або дорівнює 7, то результат буде numтому, що кожен біт &-ed з 1 є самим собою. Якщо numбільший за 7, під час &роботи комп'ютер вважатиме провідними нулями 7, які, звичайно, залишатимуться нулями після &роботи, залишиться лише задня частина. Як і у випадку з 9 & 7двійковою формою, це буде виглядати

1001 & 0111

результатом буде 0001, який дорівнює 1 в десятковій частині, і адресує другий елемент у масиві.


Ваше зауваження на півдорозі тексту, якщо довжина масиву є потужністю 2, слід викласти в першому реченні. Дуже серйозне обмеження використання цієї хитрості. Особисто я б все одно не реалізував це, код важче зрозуміти, ніж підходи if чи mod .
Ян Догген

@JanDoggen Ви маєте рацію, я поставлю це в першому реченні. Що стосується масиву, який має потужність двох, то, на мій досвід, колись це працювало більше ніж кілька разів. Можливо, тому, що це було пов'язано з мережею та графікою.
користувач3552161

1
Суть цієї публікації полягала в тому, щоб показати, що побітові оператори корисні для генерації послідовностей чисел, 0, 1, 2, 3, 0, 1, 2 ... послідовність була лише першою, що прийшла в голову.
користувач3552161

2

Я використовую їх для декількох варіантів вибору, таким чином я зберігаю лише одне значення замість 10 і більше


2

це також може бути зручно у реляційній моделі sql, скажімо, у вас є такі таблиці: BlogEntry, BlogCategory

традиційно ви можете створити nn відносини між ними за допомогою таблиці BlogEntryCategory або коли таких записів BlogCategory не так багато, ви можете використовувати одне значення в BlogEntry для з'єднання з декількома записами BlogCategory так само, як ви б це зробили з позначеними перерахунками, в більшості RDBMS також є дуже швидкі оператори, щоб вибрати в цьому стовпчику "позначений" ...


2

Коли ви хочете лише змінити деякі біти виходів мікроконтролера, але реєстр, до якого потрібно записати, - це байт, ви робите щось подібне (псевдокод):

char newOut = OutRegister & 0b00011111 //clear 3 msb's
newOut = newOut | 0b10100000 //write '101' to the 3 msb's
OutRegister = newOut //Update Outputs

Звичайно, багато мікроконтролерів дозволяють змінювати кожен біт окремо ...


якою це мова повинна бути?
Карсон Майєрс

@Carson: Нема мови, це псевдокод. Коли я насправді зробив це кілька років тому, це була асамблея, але я вважаю, що це легко зробити в C. Спасибі за голову, я
оновлю,

Я відредагував відповідь, щоб змінити коментарі, щоб виділення не було таким роздутим. І я бачу, я думав, що це може бути C, але ви використали позначення 0b ..., яке я хотів би бути доступним в C.
Карсон Майєрс

2

Якщо ви хочете коли-небудь обчислити число мод (%) певної потужності в 2, ви можете використовувати yourNumber & 2^N-1, що в цьому випадку те саме, що yourNumber % 2^N.

number % 16 = number & 15;
number % 128 = number & 127;

Це, мабуть, корисно лише в тому, що це альтернатива операції з модулем з дуже великим дивідендом, який становить 2 ^ N ... Але навіть тоді його підвищення швидкості над операцією модуля незначне в моєму тесті на .NET 2.0. Я підозрюю, що сучасні компілятори вже виконують такі оптимізації. Хтось знає більше про це?


Компілятори використовують цю оптимізацію ... але якщо ви не знали про оптимізацію, можливо, не зможете вибрати дільник, який має точну потужність 2.
Бен Войгт

Це залежить від ситуації. У C # це насправді дає різні результати, як %і операція "Рештайндер", вони негативно ставляться до негативів. Однак якщо ви перейдете uintдо цього %, компілятор C # фактично виробляє машинний код за допомогою побітового AND, коли другий аргумент - це загальновідома потужність двох.
Аарон Франке

1

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


1

У моєму запитанні є справжнє використання світу -
Відповісти лише на перше сповіщення WM_KEYDOWN?

При споживанні повідомлення WM_KEYDOWN у вікні C api біт 30 вказується попередній стан ключа. Значення дорівнює 1, якщо ключ відхилений до надсилання повідомлення, або він дорівнює нулю, якщо ключ вгору


1

Вони в основному використовуються для розрядних операцій (сюрприз). Ось кілька прикладів реального світу, знайдених у кодовій базі PHP.

Кодування символів:

if (s <= 0 && (c & ~MBFL_WCSPLANE_MASK) == MBFL_WCSPLANE_KOI8R) {

Структура даних:

ar_flags = other->ar_flags & ~SPL_ARRAY_INT_MASK;

Драйвери бази даних:

dbh->transaction_flags &= ~(PDO_TRANS_ACCESS_MODE^PDO_TRANS_READONLY);

Реалізація компілятора:

opline->extended_value = (opline->extended_value & ~ZEND_FETCH_CLASS_MASK) | ZEND_FETCH_CLASS_INTERFACE;

1

Щоразу, коли я вперше розпочав програмування на C, я розумів таблиці істинності і все це, але не все клацнуло, як реально його використовувати, поки я не прочитав цю статтю http://www.gamedev.net/reference/articles/article1563.asp (що дає приклади реального життя)


1
Ні, це не те саме. У C, якщо x == 1і y == 2, тоді x || yоцінюється до 1, а x | yдо 0. Я також не бачу, чому будь-який спосіб x^trueє кращим !x. Це більше вводити текст, менш ідіоматично, а якщо xне трапляється, boolце ненадійно.
Девід Торнлі

о, зачекайте ... так, це німо з мого боку .. Я, здається, не можу думати прямо сьогодні.
Граф

х | у приймає значення 3 (редагування: NVM, я бачу , що ти ВЕ - то редагував геть!)
стручок

1
@DavidThornley: Один випадок , коли x^trueперевершує !xє some->complicated().member->lookup ^= true; Там немає версії складеного присвоювання унарних операторів.
Бен Войгт

1

Я не думаю, що це вважається побітним, але масив ruby ​​визначає задані операції через звичайні цілі побітові оператори. Отже [1,2,4] & [1,2,3] # => [1,2]. Аналогічно для a ^ b #=> set differenceі a | b #=> union.


1

Лінійне рішення Tower of Hanoi використовує розрядні операції для вирішення проблеми.

public static void linear(char start, char temp, char end, int discs)
{
    int from,to;
    for (int i = 1; i < (1 << discs); i++) {
        from = (i & i-1) % 3;
        to = ((i | i-1) + 1) % 3;
        System.out.println(from+" => "+to);
    }
}

Пояснення цього рішення можна знайти тут

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.