Рассмотрим следующие переменные:
std::uint8_t value;
const bool bits[8] = { true, false, false, true,
false, false, true, false };
Если бы я должен был распечатать массив bools на консоль
for (int i = 0; i < 7; i++ )
std::cout << bits[i];
, это дало бы следующий вывод:
10010010
достаточно просто и прямо.
Я хотел бы создать функцию constexpr, шаблон функции, лямбду или их комбинацию, которая может выполняться во время компиляции или во время выполнения в зависимости от контекста, в котором он используется для того, чтобы я мог взять каждое из этих логических значений 0 и 1 и сохранить их в переменной value
выше. Если значение известно во время компиляции, я бы хотел, чтобы это назначение было разрешено. Если значение не известно во время компиляции, то значение будет инициализироваться 0, пока не будет обновлено, тогда оно будет использоваться в контексте времени выполнения.
Однако есть одно предупреждение, которое сначала неочевидно, но при индексации через массив индекс 0 th массива будет битом LSB value
и индекс 7 th будет MSB. Таким образом, порядок битов, которые вы видите напечатанными на экране, будет иметь шестнадцатеричное значение 0x92, но значение для сохранения должно быть 01001001, которое будет иметь шестнадцатеричное значение 0x49 или 73 в десятичном, а не 146.
Выше перечислены члены в классе, где один представляет представление значения данных, а массив bools представляет битовое представление. У меня есть несколько конструкторов, в которых один будет устанавливать данные или член-значение напрямую, а другие конструкторы будут устанавливать массив bools, но мне нужно, чтобы оба этих значения оставались параллельными друг другу в течение всей жизни объекта класса, если он обновится другой должен быть изменен. Кроме того, массив bools является членом безымянного объединения с безымянной структурой из 8 отдельных bools в виде одного бита в битовом поле. У класса также есть оператор индекса для доступа к отдельным битам в виде единичных логических значений 0 или 1.
Вот как выглядит мой класс:
constexpr unsigned BIT_WIDTH(const unsigned bits = 8) { return bits; }
struct Register_8 {
union {
bool bits_[BIT_WIDTH()];
struct {
bool b0 : 1;
bool b1 : 1;
bool b2 : 1;
bool b3 : 1;
bool b4 : 1;
bool b5 : 1;
bool b6 : 1;
bool b7 : 1;
};
};
std::uint8_t data_;
Register_8() : data_{ 0 } {}
Register_8(std::uint8_t data) : data_{ data } {
}
Register_8(const bool bits[BIT_WIDTH()]) {
for (unsigned i = 0; i < 8; i++)
bits_[i] = bits[i];
}
Register_8(const bool a, const bool b, const bool c, const bool d,
const bool e, const bool f, const bool g, const bool h) {
b0 = a; b1 = b, b2 = c, b3 = d;
b4 = e, b5 = f, b6 = g, b7 = h;
}
const std::uint8_t operator[](std::uint8_t idx) {
// I know there is no bounds checking here, I'll add that later!
return bits_[idx];
}
};
Итак, как я могу сделать каждое из значений в bits[]
отдельными битами value
, где bit[0]
- младший бит value
? Я также хотел бы сделать это в контексте, где он не будет генерировать UB! Или в STL
под c ++ 17 уже существует алгоритм, который сделает это для меня? У меня еще нет компилятора C ++ 20 ... Я пытался включить std::uint8_t
в union
, но он не работает так, как мне бы хотелось, и я не ожидал, что он будет работать либо!