Я объявил массив байтов:
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;
}
который не работает, но должен быть близок к идеальному решению. Какие-либо предложения?
Я думаю, что это должно сработать. Однако я только проверял это легко.
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);
}
Должно быть близко к идеальному решению, но
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];
0b
был официально добавлен в стандарт в C ++ 14.
Вы можете использовать эти макросы.
#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);
}
С уважением.