Если у меня есть указатель на запуск региона памяти, и я должен считать значение, упакованное в битах 30, 31, и 32 из того региона, как я могу считать то значение?
Это зависит от размера байта на вашем компьютере. Ответ будет зависеть от того, индексируете ли вы эти числа на ноль или на единицу. Следующая функция возвращает 0, если бит равен 0, и ненулевой, если он равен 1.
int getBit(char *buffer, int which)
{
int byte = which / CHAR_BIT;
int bit = which % CHAR_BIT;
return buffer[byte] & (1 << bit);
}
Если ваш компилятор не может оптимизировать достаточно хорошо, чтобы превратить операции деления и модификации в битовые операции, вы можете сделать это явно, но я предпочитаю этот код для ясности.
(Отредактировано, чтобы исправить ошибку и изменить на CHAR_BIT, что является отличной идеей.)
В 32-битной системе вы можете просто сдвинуть указатель вправо на 29. Если вам нужны битовые значения на месте, и на 0xE0000000.
Я бы, вероятно, обобщил этот ответ примерно так:
template <typename T>
bool get_bit(const T& pX, size_t pBit)
{
if (pBit > sizeof(pX) * CHAR_BIT)
throw std::invalid_argument("bit does not exist");
size_t byteOffset = pBit / CHAR_BIT;
size_t bitOffset = pBit % CHAR_BIT;
char byte = (&reinterpret_cast<const char&>(pX))[byteOffset];
unsigned mask = 1U << bitOffset;
return (byte & mask) == 1;
}
Немного проще в использовании:
int i = 12345;
bool abit = get_bit(i, 4);