Zrozumieć komputer

Dryobates

Wstęp

Do napisania tego artykułu skłoniło mnie kilka postów napisanych jakiś czas temu na forum, z których jasno wynikało, że część ludzi ma spore problemy z niektórymi podstawowymi rzeczami chociaż wydaje im się, że pewne elementy programowania opanowali. Dla tych wszystkich, który mają czasem problemy, męczą się ze wskaźnikami i innymi jest właśnie ten artykuł. Jeżeli wydaje ci się, że nie dotyczy to ciebie... to lepiej sprawdź.

Wszystko jest liczbą

Z czego składa się komputer? Jak dla nas to z procesora i pamięci. Wszystko inne możemy zaniedbać. Co to jest procesor? Jak dla nas to takie coś co liczy i zmienia zawartość pamięci. A co to w takim razie pamięć? Pamięć to takie ponumerowane po kolei pudełka. To co one zawierają? To co zechcemy. Nie muszą to być liczby!! Pamięć składa się z bitów. Bity to takie elementy, które mogą przechowywać dwa stany (przynajmniej my tak przyjmujemy). Co może zawierać jeden bit? Np. liczby: 0 i 1, -1 i 1, 1034 i 32917839, albo kolory: czerwony i zielony, fioletowy i srebrzysto-zielony, niebieski i biały, albo litery: a i b, m i k, s i c. Dowolne dwie wartości oznaczające różne rzeczy zależenie od umowy. Ale oczywiście w takim jednym bicie to dużo informacji nie zawrzemy. Co mamy zrobić np. z tymi literami, których mamy kilkadziesiąt, a możemy tylko dwie z nich na raz przechować. Możemy mieć albo a albo b. Dla pozostałych potrzebujemy innej umowy. Aby zawrzeć więcej informacji łączy się bity w większe struktury: bajty. Przyjęło się, że bajt to osiem bitów (choć bywały też w przeszłości, że inne liczby bitów). Jeden bajt to najmniejszy fragment pamięci, do którego możemy się odwołać. Przyjmijmy dla prostoty, że każdy bit może mieć wartości 0 i 1. Co możemy otrzymać z uporządkowanych zer i jedynek? Dwójkowy system liczbowy. Więcej o tym jest [[Z_pogranicza/Systemy_liczbowe|tutaj]] Dla nas istotne jest to, że na 8 bitach możemy zapisać 256 różnych wartości. Jakich? To już zależy od nas. Mogą to być np. liczby od 0 do 255 albo od -128 do 127 albo literki od "a" do "z" (jest ich mniej niż 256, ale pozostałych nie musimy wcale używać). Możemy też zapisać kolory: czerwony, zielony, niebieski, żółty, czarny, biały... łącznie 256 różnych kolorów. Możemy zapisać chociażby nazwy zwierząt: pies, kot, ryba, ptak, żaba... Wszystko zależy od umowy co oznaczać będzie konkretny stan komórki (lub żeby było prościej liczba). Któryś z matematyków powiedział kiedyś: "Wszystko jest liczbą". I tak jest w rzeczywistości. To jak my zinterpretujemy te liczby zależy wyłącznie od nas.

Wskaźniki

Skoro wiemy, że możemy każdemu obiektowi przyporządkować pewną liczbę to dla ułatwienia pamięć będziemy traktować jako ponumerowane pudełka zawierające liczby. Załóżmy, że mamy trzy komórki: 1, 2, 3. Ponieważ łatwiej operuje się nam na nazwach, to niech komórka nr 1 będzie się nazywać A, komórka nr 2 to będzie B, a komórką C będzie 3. Wrzućmy do komórki A jakąś liczbę:

A := 123;

czyli mem[1] := 123; // Do komórki o numerze 1, którą my nazwaliśmy A zapisujemy 123
A zapiszmy teraz w B liczbę 1:

B := 1;

Jak możemy zinterpretować tą liczbę? Oczywiście jako liczbę lub jakiś inny obiekt. A co by było, gdybyśmy zinterpretowali to jako adres komórki? Wobec tego 1 to adres komórki, którą nazwaliśmy A. Więc przypisanie:

B := 1;

Możemy zastąpić przez:

B := @A;

lub

B = &A; //w c++

Jak w takim razie mając wskaźnik (czyli nasze B) uzyskać dostęp do tego co jest w A? Ot tak:

B^ = A = 123 

Albo w c++

*B == A == 123

Mamy jeszcze komórkę C. Zapiszmy tam adres komórki B:

C := @B;

Jaka jest więc zawartość komórki C? C = 2, czyli adres B. Czym jest więc C^?

C^ = B = 1;

lub w c++:

*C == B == 1;

A co to (C)?

(C^)^ = B^ = A = 123

Odpowiednik w c++:

*C == *B == A == 123

A co To jest A^? To jest zawartość komórki 123, czyli... "Access ..."; Takiej komórki nie ma (lub my nie mamy do niej dostępu). Więc musimy uważać z interpretacją tych liczb. Nie każdą liczbę możemy traktować jako adres.
Wobec tego wskaźnik to nic innego jak adres komórki. Wskaźniki jednak mają nadawane pewne typy, aby kompilator wiedział jak to interpretować. Bo mając np. coś takiego:

Write(B^);

Jak ma zostać wyświetlona zawartość komórki na którą wskazuje B? Jako liczba czy jako znak?
Jeżeli zadeklarujemy B: Char; to B zostanie zinterpretowane jako wskaźnik na wartość typu Char. Czyli jeżeli B czyli A zawiera 123 to ta liczba zostanie zinterpretowana jako znak "{"; i zostanie on wyświetlony. Jeżeli B zostało zadeklarowane tak: B: Byte; to wtedy wyświetlona zostałaby liczba 123.
A co jeżeli raz chcemy wyświetlić jako liczbę a raz jako znak? Wówczas stosujemy rzutowanie (inaczej zwane wymuszeniem typu). Rzutowanie mówi kompilatorowi: "wiem, że mówiłem ci, że to jest wskaźnik na liczbę, ale tym razem interpretuj to jako znak".
I tak możemy zrobić:

</p> ```delphi type WskChar = ^Char; var A: Byte; B: ^Byte; begin A := 123; B := @B; Write('Znakiem o kodzie ', B^, ' jest ', WskChar(B)^); end; ``` Rzutowania można dokonać też na zwykłą komórkę. Nie musi to być wskaźnik. Np. w ostatnim przykładzie można zrobić tak:
  Write('Znakiem o kodzie ', B^, ' jest ', Char(B^));

Trochę pobieżnie, ale mam nadzieję, że odrobinę pomoże w zrozumieniu. Zapewne jeszcze będę uzupełniał ten artykuł, dlatego bardzo proszę o komentarze i ew. inne zagadnienia stwarzające problemy, które postaram się przybliżyć.

5 komentarzy

Z początku ten art wydawał mi się strasznie zawiły ale po dokładnym przeczytaniu rozjaśnił mi sprawę wskaźników. Thx

Kapustka: a słyszałeś o innej architekturze komputerów niż współczesne Intelowskie. Jakoś na "B" się zaczynało. Tam nie było rejestrów. W instrukcjach podawało się zamiast rejestrów miejsce w pamięci oraz długość "wirtualnego rejestru". Można było operować na słowach równych całej pamięci. Podobno całość działała jak rakieta. Problem był taki, że to nie opierało się na tranzystorach tylko na... drutach. Przez to nie wytrzymało konkurencji z tańszymi w produkcji komputerami z konwencjonalnymi rejestrami.

Arghhhhh HA ! Buachachacha
Opis mnie rozwalił.

Pomimo że ten Art jest dedykowany początkującym to czytając go doznałem olśnienia - "stan komputera" to liczba, na całą pamięć komputera można spojrzeć jak na jedną ogromną LICZBĘ ! (dlaczego tak krzyczę ?)

Kocham cię Dryo

Hahaha całkowicie mnie pojeb***
Pozdr.

"Krótki artykuł na temat kilku rzeczy sprawiających niekiedy później problemy ze względu na nienajlepsze zrozumienie pewnych podstaw."

Wybacz, że nie czytałem artu, ale opis wymiata :D

Może np. porównanie typów Byte, Word i Longword tudzież struktura słów i bajtów wyższych/niższych? Jeśli chodzi o "pomoce naukowe", możesz użyć takiego rekordu:

TLongword = record
case Integer of
0: (LW: Longword);
1: (W1, W2: Word);
2: (B1,B2,B3,B4: Byte);
end;