Записывать биты в разные байты c c ++ [дубликаты]

0

Я объявил массив байтов:

uint8_t memory[123];

который я заполнил:

memory[0]=0xFF;
memory[1]=0x00;
memory[2]=0xFF;
memory[3]=0x00;
memory[4]=0xFF;

И теперь я получаю запросы от пользователя писать в определенных битах. Например, пользователь предоставляет начальный бит (ex: 10), количество бит (ex: 9) и какие биты устанавливаются. В приведенном примере я бы получил 2 байта:

setbit[0]=0b11110010;
setbit[1]=0b00000001; //padded with zeros for extra bits

Это будет использоваться для Modbus, который является протоколом большого конца. Я придумал следующий код:

for(int j=findByteINIT;j<(findByteFINAL);j++){

   aux[0]=(unsigned char) (setbit[j]>>(startingbit-(8*findByteINIT)));
   aux[1]=(unsigned char) (setbit[j+1]<<(startingbit-(8*findByteINIT)));

   memory[j]=(unsigned char) (aux[0] & memory[j] );
   memory[j+1]=(unsigned char) (aux[1] & memory[j+1] );


   aux[0]=0x00;//clean aux
   aux[1]=0x00;

        }

который не работает, но должен быть близок к идеальному решению. Какие-либо предложения?

  • 1
    Почему вы пометили вопрос с , если ваш вопрос касается C ++? И можете ли вы объяснить подробнее, в чем проблема ? «не работает» не говорит нам много о том, с чем вы боретесь.
  • 0
    Вы положили 0b, чтобы показать, что setbit является двоичным? Веселая!
Показать ещё 5 комментариев
Теги:
bit

3 ответа

0
Лучший ответ

Я думаю, что это должно сработать. Однако я только проверял это легко.

  int start_bit = 10; int bit_count = 9;
  uint8_t setbit[2] = { 0b11110010, 0b00000001 };

  int setbit_size = (bit_count + (CHAR_BIT - 1)) / CHAR_BIT;

  int start_byte = start_bit / CHAR_BIT;
  int shift = start_bit % CHAR_BIT;
  int modified_bytes =
      bit_count ? (bit_count + shift + (CHAR_BIT - 1)) / CHAR_BIT : 0;

  for (int i = 0; i < modified_bytes; ++i) {
    uint8_t mask = 0xFF;
    if (i == 0) {
      mask <<= shift;
    } else if (i == modified_bytes - 1) {
      mask >>= CHAR_BIT - (bit_count + shift) % CHAR_BIT;
    }

    uint8_t carried = i > 0 ? (setbit[i - 1] >> (CHAR_BIT - shift)) : 0;
    uint8_t added = i < setbit_size ? static_cast<uint8_t>(setbit[i] << shift) : 0;
    memory[start_byte + i] =
        (memory[start_byte + i] & ~mask) | ((carried | added) & mask);
  }
  • 0
    Спасибо вам большое! Работало отлично!
0

Должно быть близко к идеальному решению, но

1) Вероятно, вы хотели сдвинуть влево, а затем сдвиг вправо для остальных бит

aux[0] = setbit[j] << (startingbit-(8*findByteINIT))
aux[1] = setbit[j] >> (8 - (startingbit-(8*findByteINIT)))

если начальный бит равен 10, я подозреваю, что findByteINIT станет 1, поэтому

startingbit-(8*findByteINIT)     ==  2
0b11110010 << 2    ==   0b11001000

и aux [1]:

8 - (startingbit-(8*findByteINIT))     ==  6
0b11110010 >> 6    ===  0b00000011

вместе с 8 битами, пропущенными с помощью findByteINIT:

   aux[1]    aux[0]   skipped
0b 000000011 11001000 00000000 
                  ^  11110010 starting at bit 10 

2) префикс 0b не является стандартным, он не очень портативен

3) если вы хотите установить бит, используйте или вместо и.

  memory[j]=(unsigned char) (aux[0] | memory[j] );
  // (aux[0] & memory[j] )  just clears the bits of memory[j] not set in aux[0]
  // also, shorter form:
  memory[j] |= aux[0];
  • 0
    Префикс 0b был официально добавлен в стандарт в C ++ 14.
  • 0
    Пока не в С
0

Вы можете использовать эти макросы.

#define ISBITARRAYSET(b,arr)      (((arr)[(b)/8]&(1<<((b)%8)))==0?FALSE:TRUE)
#define ISBITARRAYCLR(b,arr)      (((arr)[(b)/8]&(1<<((b)%8)))==0?TRUE:FALSE)
#define SETBITARRAY(b,arr)        ((arr)[(b)/8]|= (1<<((b)%8)))
#define CLRBITARRAY(b,arr)        ((arr)[(b)/8]&= ~(1<<((b)%8)))

Пример:

#define BIT10 0x0A;

    if( ISBITARRAYCLR(BIT10,myarray) )
    {
        SETBITARRAY(BIT10,myarray);
    }

С уважением.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню