Побитовый сдвигающий массив char 's
У меня есть массив символов, которые я пытаюсь поразрядно сдвинуть вправо >>
, а затем &
с другим массивом. Я думаю, что у меня есть неправильное представление о том, как это сделать.
Я подумал, что хотя это был массив символов, только указав my_array >>= 1
, все изменится, но я получаю сообщение об ошибке: "error: invalid operands to binary >> (have ‘char[8]’ and ‘int’)"
Побитовое сравнение, которое я пытаюсь сделать, - это массив похожих размеров, инициированный ко всем "0"... для этого я получаю: "error: invalid operands to binary & (have ‘char *’ and ‘char *’)"
Нужно ли мне преобразовать этот массив во что-то еще, прежде чем я смогу сдвинуться и сравнить?
Извините, я не был предельно ясен... Весь большой совет до этого момента, и я думаю, что я понимаю, что нет супер простого способа сделать это. Более конкретно, то, что я пытаюсь сделать, это сдвинуть бит массива WHOLE char вправо 1, добавив бит, сдвинутый с правой стороны влево на большую часть массива, поразрядное сравнение с другим массивом одинакового размера.
Технически сравнение не обязательно должно быть массивом с массивом... Мне просто нужны биты. Было бы проще преобразовать массив в нечто другое, прежде чем пытаться выполнить сдвиги/сравнения?
Ответы
Ответ 1
Вам нужно сдвинуть и сравнить пополам.
for(i = 0; i < len; ++i)
array[i] >>= 3;
например. Если вы хотите переместить биты, смещенные из одного элемента в другой, это сложнее, скажем, вы смещаетесь вправо, а затем
unsigned char bits1 = 0, bits2 = 0;
for(i = len-1; i >= 0; --i) {
bits2 = array[i] & 0x07;
array[i] >>= 3;
array[i] |= bits1 << 5;
bits1 = bits2;
}
перемещение массива в другом направлении, потому что вам нужны биты из следующего более высокого слота.
Ответ 2
/** Shift an array right.
* @param ar The array to shift.
* @param size The number of array elements.
* @param shift The number of bits to shift.
*/
void shift_right(unsigned char *ar, int size, int shift)
{
int carry = 0; // Clear the initial carry bit.
while (shift--) { // For each bit to shift ...
for (int i = size - 1; i >= 0; --i) { // For each element of the array from high to low ...
int next = (ar[i] & 1) ? 0x80 : 0; // ... if the low bit is set, set the carry bit.
ar[i] = carry | (ar[i] >> 1); // Shift the element one bit left and addthe old carry.
carry = next; // Remember the old carry for next time.
}
}
}
Ответ 3
Вам придется перемещать записи в массиве по одному. (И если вы хотите сравнить два из них, вам нужно будет сделать это элемент за элементом.)
Если вы надеялись, что бит, сдвинутый с каждого char, переместится в следующий, вам также придется позаботиться об этом вручную.
Если вы хотите, чтобы поведение смены в следующем-байте, и не против сделать ваш код неприятным и непереносимым и подверженным ошибкам, вы можете взять указатель на массив, отбросить его на что-то вроде unsigned long long *
, разыщите его и сдвиньте полученное целое число и сохраните его снова.
НО, если это поведение вам нужно, вы должны использовать целое число вместо char[8]
для начала.
(Если бы вы могли сказать больше о том, чего вы намереваетесь достичь, тогда возможны более полезные ответы.)
Ответ 4
Если вы хотите выполнять операции, такие как перемещение /OR/XOR/AND/etc.. на массивы, вы должны выполнить его в цикле, вы не можете выполнить его непосредственно в массиве.
Ответ 5
Вы можете перемещать только те элементы массивов, char (или int). Вы не можете переместить весь массив. Смещение my_array
пытается выполнить операцию сдвига по типу массива (или указателю на char), что невозможно. Сделайте это вместо:
for (i = 0; i < size; i++) {
my_array[i] >>= 1;
}
Также вы должны быть осторожны с символами, потому что они обычно подписываются, а char, содержащее отрицательное значение, будет выводить "1" слева вместо нулей. Поэтому вам лучше использовать символы без знака.
EDIT:
Вышеприведенный код упрощен. Если вы намерены перенести массив в целом, а не только на каждый байт самостоятельно, тогда вам нужно "вручную" скопировать каждый LSB в MSB байта справа. Возьмите петлю в ответ Ричарда Пеннингтона.
Ответ 6
/**
* shift a number of bits to the right
*
* @param SRC the array to shift
* @param len the length of the array
* @param shift the number of consecutive bits to shift
*
*/
static void shift_bits_right(uint8_t SRC[], uint16_t len, uint32_t shift) {
uint32_t i = 0;
uint8_t start = shift / 8;
uint8_t rest = shift % 8;
uint8_t previous = 0;
for(i = 0; i < len; i++) {
if(start <= i) {
previous = SRC[i - start];
}
uint8_t value = (previous << (8 - rest)) | SRC[i + start] >> rest;
SRC[i + start] = value;
}
}
Ответ 7
Я знаю, что это старая версия, но недавно я написал кое-что, что позволяет вам указать количество битов, на которые вы можете сдвинуться, а также в нем есть простое шифрование XOR.
//https://github.com/ashvin-bhuttoo/CryptoTest/blob/master/CryptoTest/Crypto.cpp
//CRYPTO CONFIGURATION PARAMETERS
#define BIT_SHIFT 3
#define XOR_KEY 0x3C
#define ENABLE_XOR_VARIANCE true
////////////////////////////////
int get_rs_mask(int shift)
{
switch (shift)
{
case 0:
return 0x00;
case 1:
return 0x01;
case 2:
return 0x03;
case 3:
return 0x07;
case 4:
return 0x0F;
case 5:
return 0x1F;
case 6:
return 0x3F;
case 7:
return 0x7F;
default:
throw "get_rs_mask -> Error, shift argument outside legal range 0-7";
}
}
void shift_right(char* buf, int msg_len, int shift)
{
unsigned char tmp = 0x00, tmp2 = 0x00;
for (int k = 0; k <= msg_len; k++)
{
if (k == 0)
{
tmp = buf[k];
buf[k] >>= shift;
}
else
{
tmp2 = buf[k];
buf[k] >>= shift;
buf[k] |= ((tmp & get_rs_mask(shift)) << (8 - shift));
if (k != msg_len)
tmp = tmp2;
}
}
}
int get_ls_mask(int shift)
{
switch (shift)
{
case 0:
return 0x00;
case 1:
return 0x80;
case 2:
return 0xC0;
case 3:
return 0xE0;
case 4:
return 0xF0;
case 5:
return 0xF8;
case 6:
return 0xFC;
case 7:
return 0xFE;
default:
throw "get_ls_mask -> Error, shift argument outside legal range 0-7";
}
}
void shift_left(char* buf, int msg_len, int shift)
{
char tmp = 0x00, tmp2 = 0x00;
for (int k = msg_len; k >= 0; k--)
{
if (k == msg_len)
{
tmp = buf[k];
buf[k] <<= shift;
}
else
{
tmp2 = buf[k];
buf[k] <<= shift;
buf[k] |= ((tmp & get_ls_mask(shift)) >> (8 - shift));
tmp = tmp2;
}
}
}
void crypt(char* buf, int msg_len, bool decrypt = false)
{
if (!decrypt)
{
shift_right(buf, msg_len, BIT_SHIFT);
for (int k = 0; k < msg_len; k++)
{
buf[k] = buf[k] ^ XOR_KEY ^ k * (ENABLE_XOR_VARIANCE ? 2 : 0);
}
buf[msg_len] = '\0';
}
else
{
for (int k = 0; k < msg_len; k++)
{
buf[k] = buf[k] ^ XOR_KEY ^ k * (ENABLE_XOR_VARIANCE ? 2 : 0);
}
shift_left(buf, (msg_len)-1, BIT_SHIFT);
}
}