Существует одна BEXTR (Извлечение битового поля (с регистром)) x86 для процессоров Intel и AMD и UBFX
для ARM. Существуют встроенные функции, такие как _bextr_u32()
(ссылка требует входа в систему), которые позволяют явно вызывать эту инструкцию.
Они реализуют код (source >> offset) & ((1 << n) - 1)
C: получить n
непрерывных битов из source
, начиная с бита offset
. Вот полное определение функции, которая обрабатывает крайние случаи:
#include
unsigned getbits(unsigned value, unsigned offset, unsigned n)
{
const unsigned max_n = CHAR_BIT * sizeof(unsigned);
if (offset >= max_n)
return 0; /* value is padded with infinite zeros on the left */
value >>= offset; /* drop offset bits */
if (n >= max_n)
return value; /* all bits requested */
const unsigned mask = (1u << n) - 1; /* n '1's */
return value & mask;
}
Например, чтобы получить 3
битов из 2273
(0b100011100001
), начиная с 5
-го бита, вызовите getbits(2273, 5, 3)
- он извлекает 7 (0b111
).
Например, скажем, я хочу первые 17 бит 32-битного значения; что мне делать?
unsigned first_bits = value & ((1u << 17) - 1); // & 0x1ffff
Предположим, что CHAR_BIT * sizeof(unsigned)
равно 32 в вашей системе.
Я предполагаю, что должен использовать оператор модуля, и я попробовал его и смог получить последние 8 бит и последние 16 бит
unsigned last8bitsvalue = value & ((1u << 8) - 1); // & 0xff
unsigned last16bitsvalue = value & ((1u << 16) - 1); // & 0xffff
Если смещение всегда ноль, как во всех ваших примерах в вопросе, тогда вам не нужно более общее getbits()
. Существует специальная инструкция процессора BLSMSK, которая помогает вычислять маску ((1 << n) - 1)
.
Если вы хотите, чтобы функция шаблона была другом, вы должны сказать это в объявление класса. Измените строку, объявляющую функцию друга, на следующую:
template <typename T>
friend int ask_runUI(T& a_ui);
Теперь, если ваш класс сам является шаблоном, все становится намного сложнее. Друзья по шаблонам - задача не из простых. Для этого я отсылаю вас к тому, что говорится по этому поводу в C ++ FAQ Lite .
У меня это сработало!
class AskBase {
public:
AskBase(){}
template<typename T>
friend int ask_runUI(T& a_ui);
private:
static int const s_EOF = -99;
static int const s_BACKUP = -1;
static int const s_NULL = 0;
static int const s_OK = 1;
};
//int ask_runUI()
template<typename T>
int ask_runUI(T& a_ui)
{
return AskBase::s_NULL;
}
Самым простым, вероятно, является замена static int const
члены с перечислением и не связываться с friend
s:
class AskBase {
public:
enum { Eof = -99, Null = 0, Ok = 1, Backup = -1 };
...
};