Autor: Dondu
Kurs języka C: Spis treści
Operator przesuwania bitów w lewo << przesuwa bity o zadaną ilość pozycji uzupełniając zerami najmłodsze przesunięte bity. Najstarszy bit "wypada" i jest gubiony. Przesuwać bity można o dowolną ilość pozycji.
Ponieważ podstawą kodu dwójkowego jest liczba dwa, stąd przesunięcie o jeden bit w lewo, jest równoznaczne z mnożeniem przez dwa. Analogicznie przesunięcie o dwa bity jest mnożeniem przez 4, itd. Należy oczywiście uważać, by nie przekroczyć dozwolonego zakresu typu zmiennej.
76543210 numery bitów
--------
00001111 zmienna a
--------
00011110 wynik przesunięcia bitowego w lewo o 1 pozycję: a = a<<1
--------
00001111 zmienna a
--------
00011110 wynik przesunięcia bitowego w lewo o 1 pozycję: a = a<<1
Przesuwamy bit o jeden w lewo.
Przykład 1 (w kompilatorze)
unsigned char a = 0b00001111; a = a << 1; //przesuń bity o jeden w lewo, a na najmłodszy wstaw zero
Bity można przesuwać o dowolną ilość pozycji:
Przykład 2 (w kompilatorze)
a = a << 4; //przesuń bity o cztery w lewo, a na najmłodsze wstaw zero
Najstarszy bit jest tracony.
Przykład 3 (w kompilatorze)
unsigned char a = 0b10000000; a = a << 1; //przesuń w lewo o jeden, tracimy najstarszy bit
Przekroczenie ilości bitów w zmiennej oznaczać będzie, że na wszystkich bitach pojawią się zera.
Przykład 4 (w kompilatorze)
unsigned char a = 0b10000001; a = a << 8; //przesuń w lewo o osiem pozycji, tracimy wszystkie bity
Łączenie operatorów: <<=
Operator przesunięcia w lewo może być łączony z operatorem przypisania.
Przykład 5 (w kompilatorze)
a <<= 1; //równoznaczny z: a = a << 1;
Rolowanie bitów w lewo
Rolowanie w lewo, to przesuwanie w lewo z jednoczesnym przenoszeniem wypadającego bitu na najmłodszy bit. Niestety język C, to nie assembler i nie posiada operatorów rolowania w lewo. Należy posłużyć się dodatkowym kodem. Poniżej kilka przykładów dla zmiennych typu char.
1. rolowanie w postaci funkcji z użyciem if( ):
Przykład 6 (w kompilatorze)
//funkcja rolująca bity w lewo unsigned char dd_rol( unsigned char a ) { //sprawdzamy najstarszy bit (bit tracony przy przesuwaniu w lewo) if( a & 0x80 ){ // gdy jest równy jeden return ( (a<<1) | 0x01 ); // trzeba przenieść tracony bit na najmłodszy } //gdy jest równy zero return (a<<1); //tylko przesuwamy, a standardowo na najmłodszym bicie //ląduje zero }
2. rolowanie z użyciem definicji z instrukcją wyboru (skrócony if):
Przykład 7 (w kompilatorze)
//definicja dd_rol() #define dd_rol(a) ((a&0x80)? 0x01|(a<<1) : a<<1 )
Można oczywiście dwa powyższe przykłady "wymieszać" definiują własną funkcję ze skróconym if( ).
3. Rolowanie z użyciem wstawki kodu assemblera:
Przykład 8 (w kompilatorze)
//przesuń bity o jeden w lewo, za pomocą wstawki kodu assemblera asm volatile ("rol %0" : "=r" (a) : "0" (a));
Składnia kodu
Nie ma znaczenia, czy piszesz ze spacjami, czy bez.
//dozwolone formy a = a << 1; a=a<<1; a <<= 1; a<<=1;
Ale uwaga: Nie może być spacji pomiędzy operatorami!
//niedozwolone formy a << = 1;
Ćwiczenie
Spróbuj zrozumieć poniższy kod zanim uruchomisz go w kompilatorze CManiak.
Przykład 9 (w kompilatorze)
unsigned char i; unsigned char a = 0b00000001; for(i = 0; i<9; i++){ printf("%d \n", a); a<<=1; }Kurs języka C: Spis treści
16
Nie rozumiem dlaczego w przykładzie z rolowaniem badasz if( a & 0x80 ) ? Z tego co wiem, wynikiem wewnatrz nawiasu może być 0x00 lub 0x80 - tak czy siak nie jest to jedynka (tzn 0x01) -czyli wewnątrz nawiasu wartość a&0x80 zawsze będzie różna od jedynki, a więc cały if będzie dawał zero...?
OdpowiedzUsuńWynikiem a & 0x80 (czyli koniunkcji) będzie liczba różna od zera (a dokładnie 0x80) tylko wtedy, gdy na najbardziej znaczącym 7 bicie zmiennej a będzie jedynka. W przeciwnym wypadku wyrażenie to będzie równe zero.
UsuńTestowałeś przykład w CManiaku?
Ok, mój błąd wynikał z tego że sądziłem iż tylko if(1) wykonuje komendy wstawione pod "if". Własnie widzę że jeśli pod "if" wyladuje jakakolwiek liczba różna od zera, wtedy komendy też sa wykonywane. Tak czy siak, niepotrzebnie narobiłem wiatru, sorry za zamieszanie i dzięki za szybką odpowiedź :)
Usuńwitam
OdpowiedzUsuńprzykład 8 - błąd kompilacji
Poniżej błędy oraz warning'i według szablonu:
NR_LINII_PROGRAMU : NUMER_ZNAKU_W_LINII : OPIS
In function 'main':
20:3: error: 'asm' undeclared (first use in this function)
asm volatile ("rol %0" : "=r" (a) : "0" (a));
^
20:3: note: each undeclared identifier is reported only once for each function it appears in
20:7: error: expected ';' before 'volatile'
asm volatile ("rol %0" : "=r" (a) : "0" (a));
^
pozdrawiam
michał