Я пытаюсь редактировать каждый байт буфера, изменяя младший значащий бит (LSB) в соответствии с некоторыми требованиями.
Я использую тип unsigned char для байтов, поэтому, пожалуйста, дайте мне знать ЕСЛИ это правильно / неправильно.
unsigned char buffer[MAXBUFFER];
Далее я использую эту функцию
char *uchartob(char s[9], unsigned char u)
который изменяет и возвращает первый параметр в виде массива битов. Эта функция прекрасно работает, так как биты в массиве представляют второй параметр.
Вот где начинаются хлопоты. Я собираюсь указать, что я пытаюсь сделать шаг за шагом так что вы, ребята, можете сообщить мне, где я делаю неправильный поворот.
я сохранение результата вышеуказанной функции (вызывается для каждого элемента буфера) в переменной
char binary_byte[9]; // array of bits
я тестирование LSB просто сравнивая его с каким-то флагом, как указано выше.
if (binary_byte[7]==bit_flag) // i go on and modify it like this
binary_byte[7]=0; // or 1, depending on the case
Далее я пытаюсь преобразовать массив битов двоичный_байт (это массив битов, не так ли?) обратно в байт / беззнаковый символ и обновлять данные в буфере одновременно. Я надеюсь, что я проясняю себя достаточно, поскольку я действительно смущен в данный момент.
buffer[position_in_buffer]=binary_byte[0]<<7| // actualize the current BYTE in the buffer
binary_byte[1]<<6|
binary_byte[2]<<5|
binary_byte[3]<<4|
binary_byte[4]<<3|
binary_byte[5]<<2|
binary_byte[6]<<1|
binary_byte[7];
Имейте в виду, что бит в позиции binary_byte [7] может быть изменен, вот в чем смысл всего этого.
Решение не очень элегантное, но работает, хотя я действительно не уверен в том, что я сделал (я пытался сделать это с помощью побитовых операторов, но безуспешно)
Странная вещь, когда я пытаюсь распечатать обновленный символ из буфера. У него те же биты, что и у предыдущего символа, но это совершенно другой.
Мой последний вопрос: Какой эффект оказывает изменение только младшего бита в байте? Чего мне ожидать?. Как видите, я получаю только «новых» персонажей, даже если не должен.
побитовое:
установить бит => a |= 1 << x;
сбросить бит => a &= ~(1 << x);
проверка битов => a & (1 << x);
флип бит => a ^= (1 << x)
Если вы не можете справиться с этим, вы всегда можете использовать станд :: BitSet.
Вспомогательные макросы:
#define SET_BIT(where, bit_number) ((where) |= 1 << (bit_number))
#define RESET_BIT(where, bit_number) ((where) &= ~(1 << (bit_number)))
#define FLIP_BIT(where, bit_number) ((where) ^= 1 << (bit_number))
#define GET_BIT_VALUE(where, bit_number) (((where) & (1 << (bit_number))) >> bit_number)
// это вернет 0 или 1
Вспомогательное приложение для печати битов:
#include <iostream>
#include <cstdint>
#define GET_BIT_VALUE(where, bit_number) (((where) & (1 << (bit_number))) >> bit_number)
template<typename T>
void print_bits(T const& value)
{
for(uint8_t bit_count = 0;
bit_count < (sizeof(T)<<3);
++bit_count)
{
std::cout << GET_BIT_VALUE(value, bit_count) << std::endl;
}
}
int main()
{
unsigned int f = 8;
print_bits(f);
}
Так что я все еще немного не уверен, чего вы пытаетесь достичь, но, поскольку вы пытаетесь изменить отдельные биты байта, я бы предложил использовать следующую структуру данных:
union bit_byte
{
struct{
unsigned bit0 : 1;
unsigned bit1 : 1;
unsigned bit2 : 1;
unsigned bit3 : 1;
unsigned bit4 : 1;
unsigned bit5 : 1;
unsigned bit6 : 1;
unsigned bit7 : 1;
} bits;
unsigned char all;
};
Это позволит вам получить доступ к каждому биту вашего байта и при этом получить представление вашего байта. Вот небольшой пример кода:
bit_byte myValue;
myValue.bits.bit0 = 1; // Set the LSB
// Test the LSB
if(myValue.bits.bit0 == 1) {
myValue.bits.bit7 = 1;
}
printf("%i", myValue.all);