Ответ 1
Если вы говорите об одном байте, поиск по таблице, вероятно, лучший выбор, если по какой-то причине у вас нет доступных 256 байтов.
Хотя существует несколько способов обратного порядка бит в байте, мне любопытно, что такое "самый простой" для разработчика. И, обращаясь, я имею в виду:
1110 -> 0111
0010 -> 0100
Это похоже на, но не дубликат этого вопроса PHP.
Это похоже на, но не дубликат this C вопроса. Этот вопрос требует самого простого метода для реализации разработчиком. "Лучший алгоритм" посвящен производительности памяти и процессора.
Если вы говорите об одном байте, поиск по таблице, вероятно, лучший выбор, если по какой-то причине у вас нет доступных 256 байтов.
Это должно работать:
unsigned char reverse(unsigned char b) {
b = (b & 0xF0) >> 4 | (b & 0x0F) << 4;
b = (b & 0xCC) >> 2 | (b & 0x33) << 2;
b = (b & 0xAA) >> 1 | (b & 0x55) << 1;
return b;
}
Сначала левые четыре бита заменяются правыми четырьмя битами. Затем все соседние пары меняются местами, а затем все соседние отдельные биты. Это приводит к обратному порядку.
Я думаю, что таблица поиска должна быть одним из простейших методов. Однако вам не нужна полная таблица поиска.
//Index 1==0b0001 => 0b1000
//Index 7==0b0111 => 0b1110
//etc
static unsigned char lookup[16] = {
0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe,
0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf, };
uint8_t reverse(uint8_t n) {
// Reverse the top and bottom nibble then swap them.
return (lookup[n&0b1111] << 4) | lookup[n>>4];
}
// Detailed breakdown of the math
// + lookup reverse of bottom nibble
// | + grab bottom nibble
// | | + move bottom result into top nibble
// | | | + combine the bottom and top results
// | | | | + lookup reverse of top nibble
// | | | | | + grab top nibble
// V V V V V V
// (lookup[n&0b1111] << 4) | lookup[n>>4]
Это довольно простое кодирование и проверка визуально.
В конечном итоге это может быть даже быстрее, чем полная таблица. Битовый ариф дешев, и таблица легко вписывается в строку кэша.
Для решения многих проблем см. бит-скрипичные хаки. Очевидно, что отпадает необходимость в их копировании. =)
Например (на 32-разрядном ЦП):
uint8_t b = byte_to_reverse;
b = ((b * 0x0802LU & 0x22110LU) | (b * 0x8020LU & 0x88440LU)) * 0x10101LU >> 16;
Если "просто реализовать" означает что-то, что можно сделать без ссылки на экзамене или собеседовании, то самым безопасным вариантом является, вероятно, неэффективное копирование бит по одному в другую переменную в обратном порядке (уже показано в других ответах).
Поскольку никто не опубликовал полное решение для поиска таблицы, вот мой:
unsigned char reverse_byte(unsigned char x)
{
static const unsigned char table[] = {
0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff,
};
return table[x];
}
template <typename T>
T reverse(T n, size_t b = sizeof(T) * CHAR_BIT)
{
assert(b <= std::numeric_limits<T>::digits);
T rv = 0;
for (size_t i = 0; i < b; ++i, n >>= 1) {
rv = (rv << 1) | (n & 0x01);
}
return rv;
}
EDIT:
Преобразовал его в шаблон с дополнительным битом
Две строки:
for(i=0;i<8;i++)
reversed |= ((original>>i) & 0b1)<<(7-i);
или если у вас есть проблемы с частью "0b1":
for(i=0;i<8;i++)
reversed |= ((original>>i) & 1)<<(7-i);
"original" - это байт, который вы хотите изменить. "reverse" - результат, инициализированный 0.
Хотя, вероятно, не переносимый, я бы использовал язык ассемблера.
Многие языки ассемблера имеют инструкции повернуть бит в флаг переноса и повернуть флаг переноса в слово (или байт).
Алгоритм:
for each bit in the data type:
rotate bit into carry flag
rotate carry flag into destination.
end-for
Код языка высокого уровня для этого намного сложнее, потому что C и С++ не поддерживают вращение для переноса и поворота от переноса. Флаг переноса должен быть смоделирован.
Изменить: Язык ассемблера
; Enter with value to reverse in R0.
; Assume 8 bits per byte and byte is the native processor type.
LODI, R2 8 ; Set up the bit counter
Loop:
RRC, R0 ; Rotate R0 right into the carry bit.
RLC, R1 ; Rotate R1 left, then append carry bit.
DJNZ, R2 Loop ; Decrement R2 and jump if non-zero to "loop"
LODR, R0 R1 ; Move result into R0.
Я считаю, что следующее решение проще, чем другие алгоритмы с битами, которые я видел здесь.
unsigned char reverse_byte(char a)
{
return ((a & 0x1) << 7) | ((a & 0x2) << 5) |
((a & 0x4) << 3) | ((a & 0x8) << 1) |
((a & 0x10) >> 1) | ((a & 0x20) >> 3) |
((a & 0x40) >> 5) | ((a & 0x80) >> 7);
}
Он получает каждый бит в байте и соответственно смещает его, начиная с первого до последнего.
Объяснение:
((a & 0x1) << 7) //get first bit on the right and shift it into the first left position
| ((a & 0x2) << 5) //add it to the second bit and shift it into the second left position
//and so on
Самый простой способ - это, вероятно, перебрать позиции битов в цикле:
unsigned char reverse(unsigned char c) {
int shift;
unsigned char result = 0;
for (shift = 0; shift < CHAR_BIT; shift++) {
if (c & (0x01 << shift))
result |= (0x80 >> shift);
}
return result;
}
Возможно, вас заинтересует std::vector<bool>
(то есть бит-упаковка) и std::bitset
Он должен быть самым простым в соответствии с запросом.
#include <iostream>
#include <bitset>
using namespace std;
int main() {
bitset<8> bs = 5;
bitset<8> rev;
for(int ii=0; ii!= bs.size(); ++ii)
rev[bs.size()-ii-1] = bs[ii];
cerr << bs << " " << rev << endl;
}
Другие варианты могут быть быстрее.
РЕДАКТИРОВАТЬ: я должен вам решить, используя std::vector<bool>
#include <algorithm>
#include <iterator>
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<bool> b{0,0,0,0,0,1,0,1};
reverse(b.begin(), b.end());
copy(b.begin(), b.end(), ostream_iterator<int>(cerr));
cerr << endl;
}
Во втором примере требуется расширение С++ 0x (для инициализации массива с помощью {...}
). Преимущество использования bitset
или std::vector<bool>
(или a boost::dynamic_bitset
) заключается в том, что вы не ограничены байтами или словами, но можете отменить произвольное количество бит.
НТН
Для очень ограниченного случая постоянного 8-битного ввода этот метод не требует памяти или ЦП во время выполнения:
#define MSB2LSB(b) (((b)&1?128:0)|((b)&2?64:0)|((b)&4?32:0)|((b)&8?16:0)|((b)&16?8:0)|((b)&32?4:0)|((b)&64?2:0)|((b)&128?1:0))
Я использовал это для ARINC-429, где порядок битов (порядковый номер) метки противоположен остальной части слова. Метка часто является константой и обычно восьмеричной.
Вот как я использовал ее для определения константы, потому что спецификация определяет эту метку как восьмеричное число с прямым порядком байтов 205.
#define LABEL_HF_COMM MSB2LSB(0205)
Еще примеры:
assert(0b00000000 == MSB2LSB(0b00000000));
assert(0b10000000 == MSB2LSB(0b00000001));
assert(0b11000000 == MSB2LSB(0b00000011));
assert(0b11100000 == MSB2LSB(0b00000111));
assert(0b11110000 == MSB2LSB(0b00001111));
assert(0b11111000 == MSB2LSB(0b00011111));
assert(0b11111100 == MSB2LSB(0b00111111));
assert(0b11111110 == MSB2LSB(0b01111111));
assert(0b11111111 == MSB2LSB(0b11111111));
assert(0b10101010 == MSB2LSB(0b01010101));
Поиск в таблице или
uint8_t rev_byte(uint8_t x) {
uint8_t y;
uint8_t m = 1;
while (m) {
y >>= 1;
if (m&x) {
y |= 0x80;
}
m <<=1;
}
return y;
}
изменить
Посмотрите здесь для других решений, которые могут работать лучше для вас
Перед внедрением любого алгоритмического решения проверьте язык ассемблера для любой архитектуры процессора, которую вы используете. Ваша архитектура может включать в себя инструкции, которые обрабатывают побитовые манипуляции, подобные этому (и что может быть проще, чем одна инструкция по сборке?).
Если такая инструкция недоступна, я бы предложил перейти с маршрутом таблицы поиска. Вы можете написать script/program для генерации таблицы для вас, а операции поиска будут быстрее, чем любой из алгоритмов обратного преобразования бит (за счет необходимости хранить таблицу поиска где-нибудь).
более медленная, но более простая реализация:
static int swap_bit(unsigned char unit)
{
/*
* swap bit[7] and bit[0]
*/
unit = (((((unit & 0x80) >> 7) ^ (unit & 0x01)) << 7) | (unit & 0x7f));
unit = (((((unit & 0x80) >> 7) ^ (unit & 0x01))) | (unit & 0xfe));
unit = (((((unit & 0x80) >> 7) ^ (unit & 0x01)) << 7) | (unit & 0x7f));
/*
* swap bit[6] and bit[1]
*/
unit = (((((unit & 0x40) >> 5) ^ (unit & 0x02)) << 5) | (unit & 0xbf));
unit = (((((unit & 0x40) >> 5) ^ (unit & 0x02))) | (unit & 0xfd));
unit = (((((unit & 0x40) >> 5) ^ (unit & 0x02)) << 5) | (unit & 0xbf));
/*
* swap bit[5] and bit[2]
*/
unit = (((((unit & 0x20) >> 3) ^ (unit & 0x04)) << 3) | (unit & 0xdf));
unit = (((((unit & 0x20) >> 3) ^ (unit & 0x04))) | (unit & 0xfb));
unit = (((((unit & 0x20) >> 3) ^ (unit & 0x04)) << 3) | (unit & 0xdf));
/*
* swap bit[4] and bit[3]
*/
unit = (((((unit & 0x10) >> 1) ^ (unit & 0x08)) << 1) | (unit & 0xef));
unit = (((((unit & 0x10) >> 1) ^ (unit & 0x08))) | (unit & 0xf7));
unit = (((((unit & 0x10) >> 1) ^ (unit & 0x08)) << 1) | (unit & 0xef));
return unit;
}
Может ли это быть быстрым решением?
int byte_to_be_reversed =
((byte_to_be_reversed>>7)&0x01)|((byte_to_be_reversed>>5)&0x02)|
((byte_to_be_reversed>>3)&0x04)|((byte_to_be_reversed>>1)&0x08)|
((byte_to_be_reversed<<7)&0x80)|((byte_to_be_reversed<<5)&0x40)|
((byte_to_be_reversed<<3)&0x20)|((byte_to_be_reversed<<1)&0x10);
Получает избавление от суеты использования цикла for! но эксперты, пожалуйста, скажите мне, если это эффективно и быстрее?
Эта простая функция использует маску для проверки каждого бита входного байта и передачи его в сдвиговый выход:
char Reverse_Bits(char input)
{
char output = 0;
for (unsigned char mask = 1; mask > 0; mask <<= 1)
{
output <<= 1;
if (input & mask)
output |= 1;
}
return output;
}
Этот вариант основан на BobStein-VisiBone при условии
#define reverse_1byte(b) ( ((uint8_t)b & 0b00000001) ? 0b10000000 : 0 ) | \
( ((uint8_t)b & 0b00000010) ? 0b01000000 : 0 ) | \
( ((uint8_t)b & 0b00000100) ? 0b00100000 : 0 ) | \
( ((uint8_t)b & 0b00001000) ? 0b00010000 : 0 ) | \
( ((uint8_t)b & 0b00010000) ? 0b00001000 : 0 ) | \
( ((uint8_t)b & 0b00100000) ? 0b00000100 : 0 ) | \
( ((uint8_t)b & 0b01000000) ? 0b00000010 : 0 ) | \
( ((uint8_t)b & 0b10000000) ? 0b00000001 : 0 )
Мне это очень нравится, потому что компилятор автоматически обрабатывает эту работу для вас, поэтому для этого не требуются дополнительные ресурсы.
это также можно расширить до 16-битов...
#define reverse_2byte(b) ( ((uint16_t)b & 0b0000000000000001) ? 0b1000000000000000 : 0 ) | \
( ((uint16_t)b & 0b0000000000000010) ? 0b0100000000000000 : 0 ) | \
( ((uint16_t)b & 0b0000000000000100) ? 0b0010000000000000 : 0 ) | \
( ((uint16_t)b & 0b0000000000001000) ? 0b0001000000000000 : 0 ) | \
( ((uint16_t)b & 0b0000000000010000) ? 0b0000100000000000 : 0 ) | \
( ((uint16_t)b & 0b0000000000100000) ? 0b0000010000000000 : 0 ) | \
( ((uint16_t)b & 0b0000000001000000) ? 0b0000001000000000 : 0 ) | \
( ((uint16_t)b & 0b0000000010000000) ? 0b0000000100000000 : 0 ) | \
( ((uint16_t)b & 0b0000000100000000) ? 0b0000000010000000 : 0 ) | \
( ((uint16_t)b & 0b0000001000000000) ? 0b0000000001000000 : 0 ) | \
( ((uint16_t)b & 0b0000010000000000) ? 0b0000000000100000 : 0 ) | \
( ((uint16_t)b & 0b0000100000000000) ? 0b0000000000010000 : 0 ) | \
( ((uint16_t)b & 0b0001000000000000) ? 0b0000000000001000 : 0 ) | \
( ((uint16_t)b & 0b0010000000000000) ? 0b0000000000000100 : 0 ) | \
( ((uint16_t)b & 0b0100000000000000) ? 0b0000000000000010 : 0 ) | \
( ((uint16_t)b & 0b1000000000000000) ? 0b0000000000000001 : 0 )
#include <stdio.h>
#include <stdlib.h>
int main()
{
int i;
unsigned char rev = 0x70 ; // 0b01110000
unsigned char tmp = 0;
for(i=0;i<8;i++)
{
tmp |= ( ((rev & (1<<i))?1:0) << (7-i));
}
rev = tmp;
printf("%x", rev); //0b00001110 binary value of given number
return 0;
}
typedef struct
{
uint8_t b0:1;
uint8_t b1:1;
uint8_t b2:1;
uint8_t b3:1;
uint8_t b4:1;
uint8_t b5:1;
uint8_t b6:1;
uint8_t b7:1;
} bits_t;
uint8_t reverse_bits(uint8_t src)
{
uint8_t dst = 0x0;
bits_t *src_bits = (bits_t *)&src;
bits_t *dst_bits = (bits_t *)&dst;
dst_bits->b0 = src_bits->b7;
dst_bits->b1 = src_bits->b6;
dst_bits->b2 = src_bits->b5;
dst_bits->b3 = src_bits->b4;
dst_bits->b4 = src_bits->b3;
dst_bits->b5 = src_bits->b2;
dst_bits->b6 = src_bits->b1;
dst_bits->b7 = src_bits->b0;
return dst;
}
Я думаю, что это достаточно просто
uint8_t reverse(uint8_t a)
{
unsigned w = ((a << 7) & 0x0880) | ((a << 5) & 0x0440) | ((a << 3) & 0x0220) | ((a << 1) & 0x0110);
return static_cast<uint8_t>(w | (w>>8));
}
или же
uint8_t reverse(uint8_t a)
{
unsigned w = ((a & 0x11) << 7) | ((a & 0x22) << 5) | ((a & 0x44) << 3) | ((a & 0x88) << 1);
return static_cast<uint8_t>(w | (w>>8));
}
unsigned char c ; // the original
unsigned char u = // the reversed
c>>7&0b00000001 |
c<<7&0b10000000 |
c>>5&0b00000010 |
c<<5&0b01000000 |
c>>3&0b00000100 |
c<<3&0b00100000 |
c>>1&0b00001000 |
c<<1&0b00010000 ;
Explanation: exchanged bits as per the arrows below.
01234567
<------>
#<---->#
##<-->##
###<>###
#include <stdio.h>
#include <stdlib.h>
#define BIT0 (0x01)
#define BIT1 (0x02)
#define BIT2 (0x04)
#define BIT3 (0x08)
#define BIT4 (0x10)
#define BIT5 (0x20)
#define BIT6 (0x40)
#define BIT7 (0x80)
#define BYTE_TO_BINARY_PATTERN "%c%c%c%c%c%c%c%c\n"
#define BITETOBINARY(byte) \
(byte & BIT7 ? '1' : '0'), \
(byte & BIT6 ? '1' : '0'), \
(byte & BIT5 ? '1' : '0'), \
(byte & BIT4 ? '1' : '0'), \
(byte & BIT3 ? '1' : '0'), \
(byte & BIT2 ? '1' : '0'), \
(byte & BIT1 ? '1' : '0'), \
(byte & BIT0 ? '1' : '0') \
#define BITETOBINARYREVERSE(byte) \
(byte & BIT0 ? '1' : '0'), \
(byte & BIT1 ? '1' : '0'), \
(byte & BIT2 ? '1' : '0'), \
(byte & BIT3 ? '1' : '0'), \
(byte & BIT4 ? '1' : '0'), \
(byte & BIT5 ? '1' : '0'), \
(byte & BIT6 ? '1' : '0'), \
(byte & BIT7 ? '1' : '0') \
int main()
{
int i,j,c;
i |= BIT2|BIT7;
printf("0x%02X\n",i);
printf(BYTE_TO_BINARY_PATTERN,BITETOBINARY(i));
printf("Reverse");
printf(BYTE_TO_BINARY_PATTERN,BITETOBINARYREVERSE(i));
return 0;
}
Я добавлю свое решение, поскольку пока не могу найти ничего подобного в ответах. Возможно, он немного перегружен, но он генерирует таблицу поиска, используя С++ 14 std::index_sequence
во время компиляции.
#include <array>
#include <utility>
constexpr unsigned long reverse(uint8_t value) {
uint8_t result = 0;
for (std::size_t i = 0, j = 7; i < 8; ++i, --j) {
result |= ((value & (1 << j)) >> j) << i;
}
return result;
}
template<size_t... I>
constexpr auto make_lookup_table(std::index_sequence<I...>)
{
return std::array<uint8_t, sizeof...(I)>{reverse(I)...};
}
template<typename Indices = std::make_index_sequence<256>>
constexpr auto bit_reverse_lookup_table()
{
return make_lookup_table(Indices{});
}
constexpr auto lookup = bit_reverse_lookup_table();
int main(int argc)
{
return lookup[argc];
}
Вот простое и удобочитаемое решение, переносимое на все совместимые платформы, в том числе с sizeof(char) == sizeof(int)
:
#include <limits.h>
unsigned char reverse(unsigned char c) {
int shift;
unsigned char result = 0;
for (shift = 0; shift < CHAR_BIT; shift++) {
result <<= 1;
result |= c & 1;
c >>= 1;
}
return result;
}
Я знаю, что этот вопрос устарел, но я все еще думаю, что тема актуальна для некоторых целей, и вот версия, которая работает очень хорошо и читаема. Я не могу сказать, что это самый быстрый или самый эффективный, но он должен быть одним из самых чистых. Я также включил вспомогательную функцию для простого отображения битовых комбинаций. Эта функция использует некоторые стандартные библиотечные функции вместо написания вашего собственного битового манипулятора.
#include <algorithm>
#include <bitset>
#include <exception>
#include <iostream>
#include <limits>
#include <string>
// helper lambda function template
template<typename T>
auto getBits = [](T value) {
return std::bitset<sizeof(T) * CHAR_BIT>{value};
};
// Function template to flip the bits
// This will work on integral types such as int, unsigned int,
// std::uint8_t, 16_t etc. I did not test this with floating
// point types. I chose to use the 'bitset' here to convert
// from T to string as I find it easier to use than some of the
// string to type or type to string conversion functions,
// especially when the bitset has a function to return a string.
template<typename T>
T reverseBits(T& value) {
static constexpr std::uint16_t bit_count = sizeof(T) * CHAR_BIT;
// Do not use the helper function in this function!
auto bits = std::bitset<bit_count>{value};
auto str = bits.to_string();
std::reverse(str.begin(), str.end());
bits = std::bitset<bit_count>(str);
return static_cast<T>( bits.to_ullong() );
}
// main program
int main() {
try {
std::uint8_t value = 0xE0; // 1110 0000;
std::cout << +value << '\n'; // don't forget to promote unsigned char
// Here is where I use the helper function to display the bit pattern
auto bits = getBits<std::uint8_t>(value);
std::cout << bits.to_string() << '\n';
value = reverseBits(value);
std::cout << +value << '\n'; // + for integer promotion
// using helper function again...
bits = getBits<std::uint8_t>(value);
std::cout << bits.to_string() << '\n';
} catch(const std::exception& e) {
std::cerr << e.what();
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
И это дает следующий вывод.
224
11100000
7
00000111
#define BITS_SIZE 8
int
reverseBits ( int a )
{
int rev = 0;
int i;
/* scans each bit of the input number*/
for ( i = 0; i < BITS_SIZE - 1; i++ )
{
/* checks if the bit is 1 */
if ( a & ( 1 << i ) )
{
/* shifts the bit 1, starting from the MSB to LSB
* to build the reverse number
*/
rev |= 1 << ( BITS_SIZE - 1 ) - i;
}
}
return rev;
}
xor ax,ax
xor bx,bx
mov cx,8
mov al,original_byte!
cycle: shr al,1
jnc not_inc
inc bl
not_inc: test cx,cx
jz,end_cycle
shl bl,1
loop cycle
end_cycle:
обратный байт будет в регистре bl
Как насчет этого...
int value = 0xFACE;
value = ((0xFF & value << 8) | (val >> 8);
Это старый вопрос, но никто, кажется, не показал ясный легкий путь (самый близкий был edW). Я использовал С# для проверки этого, но в этом примере нет ничего такого, что не могло бы быть легко сделано в C.
void PrintBinary(string prompt, int num, int pad = 8)
{
Debug.WriteLine($"{prompt}: {Convert.ToString(num, 2).PadLeft(pad, '0')}");
}
int ReverseBits(int num)
{
int result = 0;
int saveBits = num;
for (int i = 1; i <= 8; i++)
{
// Move the result one bit to the left
result = result << 1;
//PrintBinary("saveBits", saveBits);
// Extract the right-most bit
var nextBit = saveBits & 1;
//PrintBinary("nextBit", nextBit, 1);
// Add our extracted bit to the result
result = result | nextBit;
//PrintBinary("result", result);
// We're done with that bit, rotate it off the right
saveBits = saveBits >> 1;
//Debug.WriteLine("");
}
return result;
}
void PrintTest(int nextNumber)
{
var result = ReverseBits(nextNumber);
Debug.WriteLine("---------------------------------------");
PrintBinary("Original", nextNumber);
PrintBinary("Reverse", result);
}
void Main()
{
// Calculate the reverse for each number between 1 and 255
for (int x = 250; x < 256; x++)
PrintTest(x);
}