Autor: Dondu
Kurs języka C: Tips & Tricks - Spis treści
Rolowanie bitów, to przesuwanie bitów w prawo lub lewo z jednoczesnym przenoszeniem wypadającego bitu odpowiednio na najstarszy lub najmłodszy bit. Niestety język C, to nie assembler i nie posiada operatorów rolowania. Należy posłużyć się dodatkowym kodem.
Wszystkie poniższe przykłady dostępne są w kompilatorze CManiak, więc możesz empirycznie sprawdzić jak działają.
Rolowanie bitów w lewo
Poniżej kilka przykładów dla zmiennych typu char.
Rolowanie w lewo w postaci funkcji z użyciem if( ):
Przykład 1 (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 }
Rolowanie w lewo z użyciem definicji z instrukcją wyboru (skrócony if):
Przykład 2 (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( ).
Rolowanie w lewo z użyciem wstawki kodu assemblera:
Przykład 3 (w kompilatorze)
//przesuń bity o jeden w lewo, za pomocą wstawki kodu assemblera asm volatile ("rol %0" : "=r" (a) : "0" (a));
Rolowanie bitów w prawo
Rolowanie w prawo można zrealizować podobnie jak w lewo.
Rolowanie w prawo w postaci funkcji z użyciem if( ):
Przykład 4 (w kompilatorze)
//funkcja rolująca bity w prawo unsigned char dd_ror( unsigned char a ) { //sprawdzamy najmłodszy bit (bit tracony przy przesuwaniu w prawo) if(a & 0b00000001){ // gdy jest równy jeden return ( (a>>1) | 0b10000000 ); // trzeba przenieść tracony bit na najstarszy } //gdy jest równy zero return (a>>1); //tylko przesuwamy, a standardowo na najstarszym bicie //ląduje zero }
Rolowanie w prawo z użyciem definicji z instrukcją wyboru (skrócony if):
Przykład 5 (w kompilatorze)
//definicja dd_ror() #define dd_ror(a) ((a & 0b00000001)? 0b10000000|(a>>1) : a>>1 )
Można oczywiście dwa powyższe przykłady "wymieszać" definiują własną funkcję ze skróconym if( ).
Rolowanie w prawo z użyciem wstawki kodu assemblera:
Przykład 6 (w kompilatorze)
//przesuń bity o jeden w prawo, za pomocą wstawki kodu assemblera asm volatile ("ror %0" : "=r" (a) : "0" (a));
Kurs języka C: Tips & Tricks - Spis treści
30
Mam tutaj jeszcze jeden sposób nie wiem na ile optymalny ale też działa, bez if'a:
OdpowiedzUsuńw prawo:
x = x>>1 | x<<7;
w lewo:
x = x<<1 | x>>7;
testowałem pod linuxem
Proponuje artykuł o wstawkach asemblerowych
OdpowiedzUsuń