Вы устанавливаете оба куска каждого байта на одну и ту же вещь, потому что вы устанавливаете верхний клев равным низкому клеву в конце. Я предполагаю, что это ошибка, и что вы намеревались сдвинуть все клочки данных, перенося их с одного байта на другой и вращаясь. То есть , ABCDEF (порядок отрывков от низкого до высокого) станет FABCDE. Пожалуйста, поправьте меня, если я ошибся.
Код должен быть примерно таким:
static void crypt_enc(char *data, int size)
{
char last = 0;
//...
// Pass 2
for (i = 0; i < size; i++)
{
nibles *n = (nibles *)&data[i];
unsigned char old_low = n->low;
n->low = last;
last = n->high;
n->high = old_low;
}
((nibles *)&data[0])->low = last;
}
Теперь все в порядке? Нет. Приведение к nibbles*
является четким, только если выравнивание nibbles
не является более строгим, чем выравнивание char
. И , что не гарантируется (однако при небольшом изменении GCC генерирует тип с таким же выравниванием).
Лично я бы вообще избежал этой проблемы. Вот как я это сделаю:
void set_low_nibble(char& c, unsigned char nibble) {
// assumes nibble has no bits set in the four higher bits)
unsigned char& b = reinterpret_cast<unsigned char&>(c);
b = (b & 0xF0) | nibble;
}
void set_high_nibble(char& c, unsigned char nibble) {
unsigned char& b = reinterpret_cast<unsigned char&>(c);
b = (b & 0x0F) | (nibble << 4);
}
unsigned char get_low_nibble(unsigned char c) {
return c & 0x0F;
}
unsigned char get_high_nibble(unsigned char c) {
return (c & 0xF0) >> 4;
}
static void crypt_enc(char *data, int size)
{
char last;
//...
// Pass 2
for (i = 0; i < size; ++i)
{
unsigned char old_low = get_low_nibble(data[i]);
set_low_nibble(data[i], last);
last = get_high_nibble(data[i]);
set_high_nibble(data[i], old_low);
}
set_low_nibble(data[0], last);
}
Выполнение обратного действия означает изменение «низкого» уровня на «высокий» и наоборот; катится до последнего клева, а не до первого; и проходя данные в обратном направлении:
for (i = size-1; i >= 0; --i)
{
unsigned char old_high = get_high_nibble(data[i]);
set_high_nibble(data[i], last);
last = get_low_nibble(data[i]);
set_low_nibble(data[i], old_high);
}
set_high_nibble(data[size-1], last);
При желании вы можете избавиться от всех переводов на временный last
. Вам просто нужно сохранить последний кусочек из всех, а затем переложить кусочек напрямую, без использования другой переменной:
last = get_high_nibble(data[size-1]);
for (i = size-1; i > 0; --i) // the last one needs special care
{
set_high_nibble(data[i], get_low_nibble(data[i]));
set_low_nibble(data[i], get_high_nibble(data[i-1]));
}
set_high_nibble(data[0], get_low_nibble(data[0]));
set_low_nibble(data[0], last);