Autor: Dondu
Kurs języka C: Tips & Tricks - Spis treści
Czasami potrzebne może być dokonanie zamiany kolejności bitów w zmiennej.
meehowk3
Jak zamienić kolejność bitów? Np.: 00110001 na 10001100
Jak zamienić kolejność bitów? Np.: 00110001 na 10001100
Język C nie posiada instrukcji, która dokonuje takiej zamiany. Poniżej przykład prostej funkcji, która to umożliwia.
Przykład 1 (w kompilatorze)
//Funkcja zamiany kolejności bitów LSB <-> MSB unsigned char dd_zmien_kolejnosc_bitow(char a){ static unsigned char wynik; //zmienna wynikowa static unsigned char maska_a = 0x01; //zmienna pomocnicza static unsigned char maska_b = 0x80; //zmienna pomocnicza //dla każdego z ośmiu bitów static int i; for(i = 0; i<8; i=i+1){ //gdy bit jest jedynką dodaj go na odpowiedniej //pozycji przeciwnego mu bitu if(a & maska_a) wynik |= maska_b; maska_a<<=1; //przesuń maskę A o jeden w lewo maska_b>>=1; //przesuń maskę B o jeden w prawo } return wynik; }
Przetestuj przykład w kompilatorze CManiak. W kodzie przykładu znajdziesz linijkę pozwalającą prześledzić poszczególne fazy działania funkcji, by ją łatwiej zrozumieć.
Mikrokontrolery - specyfika
W przypadku mikrokontrolerów i niektórych budowanych na nich urządzeniach, takie rozwiązanie może być zbyt wolne. Wtedy możesz zdefiniować w pamięci programu tablicę, która zawierać będzie przeliczone wartości. Taka tablica będzie umieszczona np. pod adresem X. Wystarczy wtedy odczytać bajt spod adresu: X + liczba do zmiany. Takie rozwiązanie oczywiście oznacza, że wykorzystasz 256 bajtów pamięci programu, więc nie zawsze można sobie na to pozwolić :-)
Innym rozwiązaniem jest wykorzystanie kodu assemblera i dostępnych w nim rozkazów ROL oraz ROR, czyli przesuwania z wykorzystaniem flagi przeniesienia C (ang: carry).
Kurs języka C: Tips & Tricks - Spis treści
37
To może zaproponuję bardziej optymalną funkcję, oczywiście można ją jeszcze bardziej zoptymalizować. Ale i tak daje mniejsze narzuty na FLASH i RAM.
OdpowiedzUsuńunsigned char zmiana(char a)
{
int i, c=0;
for(i=0; i<8; i++)
{
if(a&(1<<i))
c |= (1<<7-i);
}
return c;
}