Лучший способ перебрать битовые векторы как массивы в C
Ранее, когда я перебирал битовые векторы, я использовал такие строки, как "0001", "0010", "0011" и т. Д. Я бы анализировал целые 10 оснований в строковые представления с правильной базой, используя Java, однако у меня кончились память быстро
Используя C, я ищу способ перебирать битовые векторы заданной длины. Если длина 4, я бы вызвал массив int [4] и использовал бы цикл for, чтобы заполнить каждую позицию нулями для начала. Мои проблемы начинаются, когда мне нужно добавить числа, переходя от [0,0,0,0] к [0,0,1,0], и так далее, и так далее, до состояния [1,1,1,1] ] встречается.
Я попробовал этот код ниже.
int array[4];
for (i=0; i<4; i++)
{
array[i] = 0;
}
for (i=0; i<4; i++)
{
for(x=0; x<4; x++)
{
if (array[4-x] == 0 && (4-x) != 1)
{
array = array;
}
if (array[4-x] == 1)
{
array[4-x] == 0;
array[4-x +1] ==1;
}
}
}
но это не правильно. Любая помощь будет оценена.
1 ответ
Я хотел бы использовать uint64_t
от <inttypes.h>
(который включает в себя <stdint.h>
где они на самом деле определены), до 64 бит.
Если мы пронумеровали биты от 0 до 63, где 0 - младший значащий бит, то бит i соответствует числовому значению 2i. (20 = 1, 21 = 2, 22 = 4, 23 = 8, 24 = 16 и т. Д.)
Чтобы проверить, установлен ли определенный бит (ненулевой) или очищен (ноль), мы можем использовать
static inline int bit_is_set(const uint64_t value, const int bit)
{
return !!(value & (((uint64_t)1) << bit));
}
static inline int bit_is_clear(const uint64_t value, const int bit)
{
return !(value & (((uint64_t)1) << bit));
}
Вышеуказанное возвращает True (1), если бит установлен / сброшен, и False (0) в противном случае.
(!
является оператором Not, логическое обратное. !!
является оператором Not-Not. Если x
является арифметическим выражением или числовым значением, !!x
0, если x
0 и 1, если x
ненулевой Это выглядит забавно, но помните, оно просто держит ноль ноль и преобразует ненулевое значение в 1. Довольно полезно.)
Чтобы изменить отдельный бит, мы можем использовать
static inline uint64_t set_bit(const uint64_t value, const int bit)
{
return value | (((uint64_t)1) << bit);
}
static inline uint64_t clear_bit(const uint64_t value, const int bit)
{
return value & (~(((uint64_t)1) << bit));
}
static inline uint64_t flip_bit(const uint64_t value, const int bit)
{
return value ^ (((uint64_t)1) << bit);
}
В C параметры передаются по значению, поэтому сам параметр не изменяется: функции возвращают значение с заданным битом, установленным / очищенным / перевернутым (измененным).
Ты можешь использовать
printf("value is now %" PRIu64 ".\n", value);
напечатать uint64_t value;
,
Для анализа параметров командной строки uint64_t
s, я использую что-то вроде
#include <stdlib.h>
#include <inttypes.h>
#include <stdio.h>
int main(int argc, char *argv[])
{
uint64_t a, b;
char dummy;
if (argc != 3) {
fprintf(stderr, "\n");
fprintf(stderr, "Usage: %s [ -h | --help | help ]\n", argv[0]);
fprintf(stderr, " %s A B\n", argv[0]);
fprintf(stderr, "\n");
fprintf(stderr, "This program calculates the binary OR of A and B.\n");
fprintf(stderr, "\n");
return EXIT_FAILURE;
}
if (sscanf(argv[1], " %" SCNu64 " %c", &a, &dummy) != 1) {
fprintf(stderr, "%s: Not a 64-bit unsigned integer.\n", argv[1]);
return EXIT_FAILURE;
}
if (sscanf(argv[2], " %" SCNu64 " %c", &b, &dummy) != 1) {
fprintf(stderr, "%s: Not a 64-bit unsigned integer.\n", argv[2]);
return EXIT_FAILURE;
}
printf("A = %" PRIu64 "\n", a);
printf("B = %" PRIu64 "\n", b);
printf("A | B = %" PRIu64 "\n", a | b);
return EXIT_SUCCESS;
}
Обратите внимание, что семейство функций scanf() не выдает ошибку при переполнении. Это означает, что если вы поставите 11111111111111111111111111111111
, это будет показано как-то еще, как правило, 18446744073709551615
знак равно UINT64_MAX
).
Есть способы избежать этого, проще всего написать свою собственную функцию синтаксического анализатора, но если вы всегда выводите входные переменные (как в примере программы выше), вы можете предположить, что пользователь проверит, и не будет беспокоиться об этом в типичных случаях.