typedef unsigned long bfield_t[ size_needed/sizeof(long) ];
// long because that's probably what your cpu is best at
// The size_needed should be evenly divisable by sizeof(long) or
// you could (sizeof(long)-1+size_needed)/sizeof(long) to force it to round up
Теперь каждый long в bfield_t может содержать sizeof (long) * 8 бит.
Вы можете рассчитать индекс нужного бига по:
bindex = index / (8 * sizeof(long) );
и ваш битовый номер на
b = index % (8 * sizeof(long) );
Затем вы можете найти нужный вам отрезок и затем замаскировать нужный вам бит.
result = my_field[bindex] & (1<<b);
или
result = 1 & (my_field[bindex]>>b); // if you prefer them to be in bit0
Первый из них может быть быстрее на некоторых процессорах или может спасти вас от необходимости возвращаться
выполнять операции между одним и тем же битом в нескольких битовых массивах. Это также зеркала
установка и очистка битов в поле более тесно, чем вторая реализация.
комплект:
my_field[bindex] |= 1<<b;
ясно:
my_field[bindex] &= ~(1<<b);
Вы должны помнить, что вы можете использовать побитовые операции с длинными значениями, которые содержат поля
и это то же самое, что и операции с отдельными битами.
Возможно, вы также захотите изучить функции ffs, fls, ffc и flc, если они доступны. ffs всегда должен быть доступен в strings.h
. Именно для этой цели - цепочка битов.
Во всяком случае, это найти первый набор и по существу:
int ffs(int x) {
int c = 0;
while (!(x&1) ) {
c++;
x>>=1;
}
return c; // except that it handles x = 0 differently
}
Это обычная операция для процессоров, для которой есть инструкция, и ваш компилятор, вероятно, будет генерировать эту инструкцию, а не вызывать функцию, подобную той, которую я написал. Кстати, у x86 есть инструкция для этого. Да, и ffsl, и ffsll - это одна и та же функция, за исключением длинных и длинных длинных соответственно.