Гарним прикладом здатності мови 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
, рекомендується почати з полів з
високим рівнем вирівнювання.