Menu

Маніпуляція бітами

Гарним прикладом здатності мови D генерувати код під час компіляції з mixins є маніпуляція бітами.

Проста маніпуляція бітами

D пропонує наступні оператори для маніпуляції бітами:

  • & побітове "і"
  • | побітове "або"
  • ~ побітове "ні"
  • << побітовий знаковий зсув вліво
  • >> побітовий знаковий зсув вправо (зберігає знак біта високого порядку)
  • >>> побітовий беззнаковий зсув вправо

Практичний приклад

Типовим прикладом для маніпуляції бітами є зчитування значення певного біта. D використовує core.bitop.bt для найбільш поширених завдань, проте щоб звикнути маніпулювати бітами, давайте почнемо з детальної реалізації перевірки біту:

enum posA = 1;
enum maskA = (1 << posA);
bool getFieldA()
{
    return _data & maskA;
}

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

enum posA = 1;
enum lenA = 3;
enum maskA = (1 << lenA) - 1; // ...0111
uint getFieldA()
{
    return (_data >> posA) & maskA;
}

Установка такого блоку може бути рівнозначно визначена шляхом заперечення маски і, таким чином, дозволити писати лише у заданому блоці:

void setFieldA(bool b);
{
    return (_data & ~maskAWrite) | ((b << aPos) & maskAWrite);
}

std.bitmanip на допомогу

Завжди весело писати власний код для роботи з бітами, і D пропонує для цього повний набір інструментів. Однак, у більшості випадків такий код доведеться постійно копіювати, а це збільшить можливість отримати помилки і ускладнить підтримку коду. Тому, D має модуль std.bitmanip, який допомагає писати простий у підтримці та легкочитаємий код для маніпуляції бітами, використовуючи mixins - без шкоди для продуктивності.

Подивіться на розділ вправи. Визначено команду BitVector, але вона як і раніше використовує тільки X бітів і майже не відрізняється від звичайної структури.

std.bitmanip та core.bitop містять більше помічників, які дуже корисні для програм, що вимагають зниженого споживання пам'яті.

Відступ і вирівнювання

Так як компілятор додасть заповнення для змінних, які за розміром менші, ніж визначено схемою розташування пам'яті OS (size_t.sizeof), наприклад, для типів bool, byte та char, рекомендується почати з полів з високим рівнем вирівнювання.

Поглиблення

rdmd playground.d