Учитывая char *
массивов, вы можете легко реализовать операторы set
и get
для установки и извлечения, соответственно, i-го бита:
void set(char *a, int position, int value) {
int byte = position >> 3;
int bit = 1 << (position & 0x07); // 00000001b to 10000000b
a[byte] = value ?
a[byte] | bit : // on
a[byte] & ~bit; // off
}
int get(char *a, int position) {
return a[position>>3] & (1 << (position&0x07)) ? 1 : 0;
}
Это может быть сделано немного быстрее с помощью встроенных компиляторов, чтобы получить и деление, и модуль одновременно, и, возможно, есть некоторый побитовый трюк, чтобы избежать перехода в 'set' - но, надеюсь, этот код передает суть операции.
Реализация желаемой функции по сути является расширением кода в моей функции set
, где вместо того, чтобы касаться только одного бита, вы продолжаете, пока у вас не закончатся биты для изменения, начиная с указанного смещения.
Редактировать: добавление побитового трюка из этого ответа для удаления ветвления из set
:
void set(char *a, int position, int value) {
int byte = position >> 3;
int offset = position & 0x07);
a[byte] = (a[byte] & ~(1<<offset)) | (value<<offset);
}
Обратите внимание, что для этой версии value
должно быть либо 0, либо 1; предыдущая версия работала бы с любым значением false или true (= ноль против ненулевого значения).