Chociaż programowanie staje się coraz bardziej wysokopoziomowe, zdarza się, że trzeba zejść na niziny i wykonać kilka “staromodnych” operacji’. Dotyczy to na przykład działań na bitach, co jest zazwyczaj związane jest z koniecznością interpretacji różnych sposobów reprezentowania danych. Bardzo dobrym przykładem jest chociażby blokowanie i odczyt/zapis powierzchni (tekstur, bufora ramki, głębokości, itd.) w bibliotekach graficznych. Format pikseli może być bowiem taki, że dostanie się do informacji o kolorze będzie wtedy wymagało nieco zachodu, w tym także operacji na pojedynczych bitach.
Ale nie tym będę się zajmował, gdyż, jak wiadomo, jest to przecież proste ;-) Dzisiaj chciałem zwrócić uwagę na pewien niezwykle ważny szczegół związany z operacjami bitowymi, mogący powodować powstawanie błędów, które na pierwszy rzut oka wyglądają cokolwiek tajemniczo. Chodzi mianowicie o różnice między typami liczbowymi ze znakiem i bez znaku, kiedy chodzi właśnie o działania z użyciem operatorów bitowych.
Ogólna zasada brzmi, aby – jeśli to tylko możliwe – korzystać wtedy wyłącznie z typów liczbowych bez znaku. Mogłoby się wydawać, że to żadna różnica, skoro i tak nie interesują nas wartości zmiennych w interpretacji liczbowej, a jedynie “gołe” bity. Rzecz w tym, że dla kompilatora takie rozróżnienie zazwyczaj nie istnieje i poza nielicznymi wyjątkami (jak std::bitset
w C++) należy stosować zmienne typu liczbowego, gdy operujemy na bitach.
Istnieją zaś przypadki, kiedy uznawanie jakiegoś ciągu bitów za liczbę ze znakiem powoduje zupełnie inne efekty niż interpretacja tego samego ciągu jako liczby bez znaku. Naturalnie cały czas mówimy o korzystaniu jedynie z operatorów bitowych! Co to za szczególne sytuacje?…
-1
. Po rozszerzeniu wartości -1
na 32 bity otrzymamy znów ciąg samych jedynek – lecz tym razem aż trzydziestu dwóch, bo taka jest 32-bitowa reprezentacja liczby -1
. Dla typów bez znaku otrzymalibyśmy naturalnie ciąg 24 zer i 8 jedynek.>>
, lecz z drugiej strony wcale nie jest powiedziane, że zawsze stosowany jest wariant bez znaku dla typów signed
i bez znaku dla unsigned
. Jest to zależne od kompilatora, choć rzecz jasna większość zachowuje się w tym względzie odpowiednio rozsądnie.Tym niemniej nie powinno się na takiej dobroci polegać i należy, do celów działania na bitach, używać typów bez znaku. Inna sprawa, że niektóre języki programowania takich typów w ogóle nie mają i wtedy możemy napotkać (nie)wielki problem. Ale to już całkowicie odrębny temat do narzekania i poruszę go może przy innej okazji :)
#offtopic
Xion, wczoraj byl Dzien Liczby PI a Ty nie napisales nic o tym :( zawiodlem sie :P
Przyznam szczerze, że nie wiedziałem. Z drugiej jednak strony, to raczej dzień dla matematyków, bo dla programisty interesująca jest co najwyżej stała D3DX_PI :)
@Xion: Nie usprawiedliwiaj się – jak znam Ciebie to gdybyś wiedział napisałbyś całe wypracowanie o tym :)
I nawet wiadomości nie oglądasz bo tam informowali o tym ^^