Jason. Cała informatyka w jednym miejscu!

W tę dużo swobodniejszą sobotę mam kolejne zjawisko programistyczne do omówienia. Dotyczy ono liczbowych typów danych, a dokładniej ich minimalnych i maksymalnych zakresów. Ich osiągnięcie może być czasem nieprzewidywalne i spowodować "zapętlenie", które bardziej kulturalnie wypadałoby nazwać "przekroczenie zakresu liczb całkowitych".

CZEGO DOTYCZY PRZEKROCZENIE ZAKRESU LICZB CAŁKOWITYCH?

Zjawisko to (ang. "integer overflow") polega na "wyjściu" poza zakres bitowy danej liczby (bo przypominam, że komputer przechowuje wszystkie liczby całkowite w systemie binarnym, który był omawiany wcześniej) i spowodowanie "odliczanie od nowa". Pomimo nazwy, to nie dotyczy jedynie liczb całkowitych, bo to przekroczenie może wystąpić także w liczbach zmiennoprzecinkowych!

ZMIENNA BEZ ZNAKU

Załóżmy, że dla uproszczenia tłumaczenia mamy zmienną typu "unsigned char" ("unsigned" oznacza liczbę bez znaku czyli nie można do niej przypisać liczby ujemnej, ale w zamian za to ma podwojony zakres liczb dodatnich - <0-255> zamiast <-128-127>). "char" przeznaczone jest głównie do przechowywania znaków w systemie ASCII, ale małe liczby całkowite również może przechowywać. Przechodząc do rzeczy załóżmy, że obecnie posiada wartość równą 254 i chcemy sprowokować przekroczenie zakresu liczb całkowitych.

1 1 1 1 1 1 1 0

Gdy dodamy do obecnej wartości jedynkę, to osiągamy maksymalny zakres liczby, ale nic złego się jeszcze nie dzieje...

1 1 1 1 1 1 1 1

W tym momencie mamy cały bajt zapełniony jedynkami, zatem liczba jest równa 255. Gdy teraz ponownie zlecimy komputerowi inkrementację (zwiększymy liczbę dokładnie o 1), otrzymamy coś takiego:

0 0 0 0 0 0 0 0

To jest efekt uboczny, który oznacza przekroczenie zakresu liczb całkowitych. Spowodowało to "przekręcenie się" licznika, które "powróciło" do minimalnej wartości mogącej się zmieścić w jednym bajcie.

ZMIENNA ZE ZNAKIEM

Zobaczmy co by się stało, gdybyśmy mieli zmienną ze znakiem czyli "signed char". Mamy liczbę 127 (czyli maksymalny zakres) i dodajemy jedynkę. Wówczas otrzymujemy taki ciąg bitów:

1 0 0 0 0 0 0 0

Reprezentacja bitowa wygląda teraz tak. Głowicie się dlaczego na początku jest jedynka? Ponieważ gdy jest to zmienna ze znakiem, pierwszy bit staje się tak zwanym "bitem znaku" kontrolującym znak zmiennej czy ma to być wartość ujemna, czy dodatnia (ma to ścisły związek z kodem uzupełnień do dwóch). To dlatego występuje taka różnica w zakresach pomiędzy "signed", a "unsigned". Następuje przekroczenie zakresu liczb całkowitych i wejście na minimalny zakres ujemny jakim jest liczba -128.


Na koniec dodam, że tak następuje z każdą liczbą całkowitą. Czy to "short", czy "long", występuje to samo zagrożenie. Nie jest one postrzegane jako błąd przez kompilator i program Was nie powiadomi o takiej sytuacji, zatem sami musicie się przed tym uchronić.

PODOBNE ARTYKUŁY