2010-10-12 2 views
1

типа данных является символом, и шаблон, следует:немного замены с типом полукокса в C

Источника байты: [0] [1] [2] [3] [4] [5] [6] [7]

назначения: [6] [7] [4] [5] [2] [3] [0] [1]

, например, если я передать символ, 29 к этой функции , он выполнит замену и возвращает значение типа символа, которое равно 116.

Как я могу сделать обмен?

спасибо.

========================

Просто интересно, если я могу сделать, таким образом?

unsigned char mask = 128; 
char num = 0, value1 = 29; 
int i, a; 

for(i = 0; i < 8; i++) { 
    if (i == 0 || i == 1 || i == 6 || i == 7) 
    a = 6; 
    else 
    a = 2; 

    if(i < 4) 
    num = ((value1 & mask) >> a); 
    else 
    num = ((value1 & mask) << a); 

    result = (result | num); 

    if(i<7) 
    mask = mask >> 1; 
} 
+0

Да? У вас есть 3-битное значение, которое вы вращаете? Но в чарке? С 8 бит? Три не делятся на восемь чисто. –

+0

Что? Его пример - «29 = 00011101», и он преобразует его в «116 = 01110100», переставляя биты –

+0

. Это для исправления адресов после выполнения FFT/DFT на месте? Он выглядит знакомым ... –

ответ

4

Я обычно схожу с битов в другую сторону, так что бит 0 - это LSB.Следуя вашей схеме нумерации:

unsigned char src = 29; 
unsigned char dst = 0; 
dst = (((src & 0x80) >> 6) | // bit 0 
     ((src & 0x40) >> 6) | // bit 1 
     ((src & 0x20) >> 2) | // bit 2 
     ((src & 0x10) >> 2) | // bit 3 
     ((src & 0x08) << 2) | // bit 4 
     ((src & 0x04) << 2) | // bit 5 
     ((src & 0x02) << 6) | // bit 6 
     ((src & 0x01) << 6) // bit 7 
    ); 

Если, конечно, вы не нумерацией их «правильный путь», но рисунок их «в обратном направлении», - тогда как раз обратное, что я сделал выше. (Не то, что я пытаюсь начать религиозную войну здесь ...)

+0

Есть очевидные способы сделать это более эффективным. Я оставляю код выше как есть для ясности, оптимизация остается в качестве упражнения для читателя. – bstpierre

+2

Downvoter должен быть другим-Endian? ;) – bstpierre

+0

Я бы сказал, что нумерация битов не имеет значения для этой проблемы. – 2010-10-12 18:27:07

3

См. "Последовательности реверсивного разряда" на странице Bit Twiddling Hacks.

Кроме того, если вы хотите сделать это самостоятельно:

Чтобы прочитать п -ю бит: int bit = value & (1 << n); Если бит не установлен, bit 0.

Для установки н -й бит: value |= 1 << n; (значение = значение ИЛИ (1 сдвинуты на п цифр))

Чтобы очистить п -й бит: value &= ~(1 << n); (значение = значение, а не (1, сдвинутую п цифр))

0

чередовать переноса http://en.wikipedia.org/wiki/Bitwise_operation#Rotate_through_carry

Так что это будет работать:

myByte = myByte << 2 | myByte >> 6; 
+0

Прост в ассемблере, но как бы вы это сделали в C? – DarkDust

+0

Обновлен с ответом. –

+0

Это работает для меня, но я не знаю почему. Разумеется, сдвиг правых 8 бит дает нуль? –

4

или таблицы поиска

только в случае, если вы не понимаете, что. Вот более подробно

Для каждого из 256 возможных входов работать ответ (вручную)

затем сделать

unsigned char answers[256] = {0x00, 0x40,0x21.....}; 
unsigned char answer = answers[input]; 

Спешу добавить, что значения, которые я дал в пример - и конечно, неверны

+0

+1 Эта операция кажется очень сложной, что может быть лучшим вариантом из 256 байтов. – cobbal

1

Первый своп нижние четыре бита с более высокими четырьмя битами, а затем поменять все соседние пары битов:

dst = src; 
dst = ((dst & 0xF0) >> 4) | ((dst & 0x0F) << 4); 
dst = ((dst & 0xCC) >> 2) | ((dst & 0x33) << 2); 
0
source byte: [01][23][45][67] to 
destination: [67][45][23][01] 

Реализация:

unsigned char shiftit(unsigned char in) { 
    unsigned char out; 

    out = (
    ((in & 0xC0) >> 6) + /* top 2 to bottom 2 */ 
    ((in & 0x30) >> 2) + /* centre-left 2 to centre-right */ 
    ((in & 0x0C) << 2) + /* centre-right 2 to centre-left */ 
    ((in & 0x03) << 6) /* bottom 2 to top 2 */ 
); 

    return(out); 
} 

Возвращает 116 при вызове shiftit(29).

Смежные вопросы