Bity bez znaku

2008-03-14 22:58

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?…

  • Jedna z nich dotyczy automatycznego rzutowania typów mniejszych na większe. Jeśli mamy krótki ciąg bitów, zapisany np. w zmiennej o rozmiarze 1 bajta, i chcemy go przepisać do zmiennej o większym rozmiarze, to cała operacja jest w miarę oczywista dla typów bez znaku. W nowym słowie stare bity zostaną umieszczone na najmniej znaczących pozycjach, zaś reszta zostanie wypełniona zerami.
    Natomiast dla typów ze znakiem przepisywanie dotyczyć będzie liczby reprezentowanej przez rzeczone bity, a nie ich samych. Jeśli więc mamy np. ciąg ośmiu jedynek, to przy standardowym sposobie zapisywania liczb całkowitych oznacza on po prostu -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.
  • Druga uwaga odnosi się do operacji przesunięcia bitowego w prawo, które może mieć dwa warianty. Nazywają się one… przesunięciem ze znakiem i bez znaku, zaś różnica między nimi polega na tym, czym są wypełniane wolne miejsca pojawiające się z lewej strony przesuwanego słowa. W pierwszym przypadku jest to najbardziej znaczący bit (zwany często bitem znaku dla typów ze znakiem, nawet jeśli faktycznie nim nie jest). W drugim zaś lewa strona jest wypełniana po prostu zerami.
    Kłopot w tym, że nie zawsze wiadomo, którego rodzaju przesunięcia akurat użyjemy. W C++ na przykład zasadniczo zależy to od typu argumentów operatora >>, 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 :)

Be Sociable, Share!
Be Sociable, Share!
Tags: ,
Author: Xion, posted under Programming »


3 comments for post “Bity bez znaku”.
  1. yomyn:
    March 15th, 2008 o 15:38

    #offtopic
    Xion, wczoraj byl Dzien Liczby PI a Ty nie napisales nic o tym :( zawiodlem sie :P

  2. Xion:
    March 15th, 2008 o 16:54

    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 :)

  3. moriturius:
    March 16th, 2008 o 6:23

    @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 ^^

Comments are disabled.
 


© 2023 Karol Kuczmarski "Xion". Layout by Urszulka. Powered by WordPress with QuickLaTeX.com.