Записывать диапазон битов

У меня есть класс для работы с битами в массиве байт, нужно сделать функцию для установки диапазова бит в байте.

Например есть допустим нулевой байт _arr[0] = 152 (10011000) После вызова setBit(0, 2, 7, 51) должно получиться 204 (11001100)

Не могу придумать как заменить часть байт. Пытался сделать что-то на подобии setBit для одного бита и цикла, но не получилось, как можно это сделать? Вот часть класса:

    byte* _arr = new byte[_size]();

    void checkOutOfBounds(int byteNumber, int bitStartNumber, int bitEndNumber) {
        if (byteNumber > _size-1)
            throw "BytesIsOutOfBounds";

        if (bitStartNumber > bitEndNumber)
            throw "BytesIsOutOfBounds";
        if (bitEndNumber > 7)
            throw "BitsIsOutOfBounds";
    }
    
    // Для одного бита
    void setBit(int indexByte, int indexBit, byte value) {
        checkOutOfBounds(indexByte, indexBit, indexBit);

        if (value == 0)
            _arr[indexByte] &= (0xff ^ (1 << indexBit));
        else if (value == 1)
            _arr[indexByte] |= (1 << indexBit);
    }
  
    // Для диапазона бит
    void setBit(int indexByte, int indexBitStart, int indexBitEnd, byte value) {
        checkOutOfBounds(indexByte, indexBitStart, indexBitEnd);


    }

Ответы (1 шт):

Автор решения: avp

Обычно для установки битового поля в целочисленном значении x в значение f_val используют вот такую пару макросов

#define MASK(w) ((1 << w) - 1)
#define SET_FIELD(x, f_ofs, f_width, f_val) ((x & ~(MASK(f_width) << f_ofs)) | \
                         ((f_val & MASK(f_width)) << f_ofs))

Т.е. сначала нам надо обнулить все биты поля, задаваемого смещением младшего бита (f_ofs) и его размера в битах (f_width).
Для этого мы делаем маску размером f_width бит, состоящую их единиц.

Т.о.
x & ~(MASK(f_width) << f_ofs) сбросит биты поля,
f_val & MASK(f_width) оставит в новом значении только биты поля,
а (...) | ((f_val & MASK(f_width)) << f_ofs) установит новое значение битов поля

→ Ссылка