Object Pascal/Typy zmiennych
Typy zmiennych określają zewnętrzną postać zmiennej, czyli zakres jej wartości i zestaw dozwolonych operacji, które może na niej wykonać programista, a także jej reprezentację wewnętrzną, czyli sposób traktowania je przez inne obiekty programu.
Typ prosty
edytujPorządkowy
edytujCałkowity
edytujTyp predefiniowany.
Typy ogólne
edytujNazwa typu | Zakres | Format |
---|---|---|
Integer | typ zależny od typu programowania, najczęściej od -32768 do 32767 | ze znakiem, 16 lub 32 lub 64 bitowy (w zależności od platformy na którą programujemy) |
Cardinal | typ zależny od typu programowania, najczęściej 0..4294967295 | bez znaku, 16 lub 32 lub 64 bitowy (w zależności od platformy na którą programujemy) |
Typy podstawowe
edytujNazwa typu | Zakres | Format |
---|---|---|
ShortInt | –128..127 | ze znakiem, 8-bitowy |
SmallInt | –32768..32767 | ze znakiem, 16-bitowy |
LongInt | –2147483648..2147453647 | ze znakiem, 32-bitowy |
Int64 | –2^64..2^64–1 | ze znakiem, 64-bitowy |
Byte | 0..255 | bez znaku, 8-bitowy |
Word | 0..65535 | bez znaku, 16-bitowy |
LongWord | 0..42849567295 | bez znaku, 32-bitowy |
QWord | 0 .. 18446744073709551615 | bez znaku, 64-bitowy |
Dodatkowe informacje
edytujPredefiniowane w module System stałe MaxLongint i MaxInt określają maksymalną wartość w typach LongInt i Integer.
Logiczny
edytujTyp predefiniowany.
Nazwa typu | Format |
---|---|
Boolean | 8 - bitowy |
ByteBool | 8 - bitowy |
WordBool | 16 - bitowy |
LongBool | 32 - bitowy |
Wartością zmiennej typu logicznego może być predefiniowana stała FALSE lub TRUE.
Znakowy
edytujTyp predefiniowany.
Typy podstawowe
edytujNazwa typu | Format | Uwagi |
---|---|---|
AnsiChar | 8 - bitowy | rozszerzony zestaw znaków ASCII (standard 7 bitów) |
WideChar | 16 - bitowy | zestaw znaków Unicode |
Typ ogólny
edytujNazwa typu | Format | Uwagi |
---|---|---|
Char | 8 - bitowy | zgodny z typem AnsiChar w Object Pascal |
Wyliczeniowy
edytujTyp niepredefiniowany, wymaga opisu programisty.
Definicja typu
edytujtype identyfikator-typu = (lista identyfikatorów)
Przykład
edytujtype samochody = (fiat, polonez, opel, volkswagen); //Ord(fiat) = 0 //Ord(polonez) = 1 itd. var x,y:samochody; begin x:=polonez; //x – 00000001 (liczba 1) y:=opel; //y – 00000010 (liczba 2) end;
Uwagi dotyczące stosowania typów wyliczeniowych
edytuj- Element tego typu zajmuje 8 lub 16 bitów.
- Identyfikatory na liście muszą być różne, błędna jest na przykład deklaracja
type znaki = (a,b,b,c)
- W dwóch różnych typach o tym samym zasięgu nie może wystąpić ten sam identyfikator, np. w zasięgu deklaracji typu samochody błędna jest deklaracja
type ciezarowki = (opel, volkswagen, scania)
- Porządek w typie wyliczeniowym jest zgodny z kolejnością wyliczenia w definicji typu.
- Wartości zmiennych tego typu nie można wypisać standardową procedurą write.
- Nie można na nich wykonywać operacji arytmetycznych.
- Maksymalna ilość elementów to 256.
Okrojony
edytujTyp niepredefiniowany, wymaga opisu programisty. Służy do definiowania podzbiorów dowolnego zbioru wartości określonego przez typy porządkowe.
Definicja
edytujtype identyfikator-typu = stala1 .. stala2;
Z każdym typem okrojonym związany jest bazowy, macierzysty typ porządkowy i obie stałe muszą być tego typu, przy czym ord(stala1) <= ord(stala2). Pierwsze wyrażenie stałe nie może zaczynać się od ‘(‘.
Przykład
edytujconst a = 5; b = 2; type sam = fiat .. opel; // typ bazowy samochody znaki = '!' .. '+'; // typ bazowy Char zakres1 = 2+5 .. 2*5; // typ bazowy Byte zakres2 = b+a .. b*a; // typ bazowy Integer
Rzeczywisty
edytujTyp predefiniowany. W odróżnieniu od typów całkowitych pozwala na operacje zmiennoprzecinkowe.
Typy podstawowe
edytujNazwa typu | Zakres | Znaczące cyfry | Format |
---|---|---|---|
Real48 | 2.9 x 10^–39 .. 1.7 x 10^38 | 11–12 | 48-bitowy |
Single | 1.5 x 10^–45 .. 3.4 x 10^38 | 7–8 | 32-bitowy |
Double | 1.5 x 10^–309 .. 1.7 x 10^309 | 15–16 | 64-bitowy |
Extended | 3.6 x 10^–4951 .. 1.1 x 10^4932 | 19–20 | 80-bitowy |
Comp | –2^63 .. 2^63 –1 | 19–20 | 64-bitowy |
Currency | –922337203685477.5808 .. 922337203685477.5807 | 19–20 | 64-bitowy |
Typ ogólny
edytujNazwa typu | Zakres | Znaczące cyfry | Format |
---|---|---|---|
Real | 5.0 x 10^–324 .. 1.7 x 10^308 | 15–16 | 64-bitowy |
Dodatkowe informacje
edytuj- Typ Extended zapewnia najlepszą precyzję, nie jest jednak zalecany, gdy aplikacja ma być uruchamiana na różnych platformach.
- Typ Comp służy do pamiętania dużych liczb całkowitych, nie jest jednak typem porządkowym (nie można go np. inkrementować), zachowany dla zgodności z wersjami wcześniejszymi, zaleca się używać typu Int64.
- Typ Currency ma zastosowanie do obliczeń pieniężnych.
Typ łańcuchowy
edytujTyp łańcuchowy służy do reprezentowania ciągów znaków.
Łańcuchowy krótki
edytuj- string - w zasięgu takiej dyrektywy {$H-},
- string[zakres] - zakres mniejszy lub równy od 255,
- shortstring
Łańcuchowy długi
edytuj- string - w zasięgu dyrektywy {$H+} (ustawienie standardowe)
- ansistring;
Łańcuch znaków dwubajtowych
edytuj- widestring
Typ strukturalny
edytujTablicowy
edytujTyp przeznaczony do struktur składających się z wielu elementów konkretnego typu.
Tablice statyczne
edytujDeklaracja typu tablicowego:
type identyfikator_typu = array [typy_indeksowe] of typ_bazowy;
gdzie:
- typy_indeksowe – oddzielone przecinkami opisy typów porządkowych;
- typ_bazowy – dowolny typ prosty lub strukturalny.
Przykłady:
type Kolor = (bialy, zielony, czarny); Ttab1 = array [5..8] of array [Boolean] of array [Kolor] of real; Ttab2 = array [5..8, Boolean] of array [Kolor] of real; Ttab3 = array [5..8] of array [Boolean, Kolor] of real;
Deklaracja zmiennej w typie tablicowym:
var liczba: array [1..100] of integer;
W nawiasach kwadratowych zapisywany jest zakres indeksów tablicy w postaci: od..do. Indeks tablicy musi należeć do typu porządkowego, ograniczenia (od i do) nie mogą być zmiennymi. Ograniczeniom nie podlega zakres indeksów (jedyny warunek to indeks od musi być mniejszy od indeksu do. Typ_bazowy może być typem prostym, ale także typu strukturalnego.
Istnieją również tablice wielowymiarowe, np. dwuwymiarowa:
var liczba: array[1..10] of array[1..10] of integer;
albo dla skrócenia zapisu:
var liczba: array[1..10,1..10] of integer;
Nie ma ograniczeń na liczbę wymiarów tablicy, najczęściej stosuje się tablice jedno- i dwuwymiarowe.
Tablice dynamiczne
edytujDeklaracja:
type identyfikator_typu = array of typ_bazowy; //tablica jednowymiarowa type identyfikator_typu = array of array of typ_bazowy //tablica 2-wymiarowa
Informacje:
- Zmienne tego typu zajmują 32 bity pamięci.
- Pamięć na tablicę alokowana jest w wyniku wykonania procedury SetLength (zmienna, indeksy) lub w wyniku przypisania.
- Pamięć jest zwalniana w wyniku przypisania zmienna := nil; lub w wyniku wykonania procedury Finalize (zmienna).
Rekordowy
edytujTypem rekordowym nazywamy złożoną strukturę danych, której elementy (pola), mogą być różnych typów (prostych i strukturalnych).
Deklaracja typu rekordowego
edytujtype identyfikator_typu = record {lista_deklaracji_pól}; end;
gdzie lista_deklaracji_pól ma postać:
lista_identyfikatorów_pól : opis-typu;
Ważne informacje
edytuj- Ostatnie pole może być polem wariantowym postaci:
case pole_wyróżnikowe of wykaz_wariantów;
- Pole_wyróżnikowe może być identyfikatorem typu porządkowego lub deklaracją zmiennej porządkowej.
- wykaz_wariantów ma postać:
lista-etykiet-wyboru : (lista-deklaracji-pól)
- Pola muszą mieć różne identyfikatory.
- Żadne pole wariantowe nie może być:
- typu łańcuchowego długiego,
- typu tablicy dynamicznej,
- typu wariantowego,
- typu łącza programowego.
Przykład:
edytujtype Data = record Dzien: 1..31; Miesiac: 1..12; Rok: integer; end;
Zbiorowy
edytujTyp zbiorowy jest zbiorem potęgowym typu porządkowego o maksymalnie 256 elementach.
Deklaracja typu
edytujtype identyfikator_typu = set of typ_porządkowy;
Wartościami zmiennych typu zbiorowego są dowolne podzbiory zbioru bazowego, łącznie ze zbiorem pustym. Konstruktor zbioru ma postać [ ].
Przykłady:
edytujtype Samochody = (fiat, polonez, opel, volkswagen); var A : set of samochody; B : set of 0..3; C : set of 'a'..'z'; begin A:= [ ]; A:= [opel]; B:= [1,3]; C:= ['a'..'f']; end.
Na zmiennych zbiorowych można wykonywać:
- operacje mnogościowe,
- operacje porównań,
- operację należenia do zbioru in,
- procedury:
include(zb, el) zb:=zb+[el] exclude(zb, el) zb:=zb-[el]
Plikowy
edytujKlasowy
edytujTyp klasowy jest podobny do typu rekordowego, posiada jednak dodatkowo metody (procedury i funkcje). Słowo class, oznacza taką strukturę, która posiada konstruktory (słowo kluczowe constructor) i destruktor (destructor), deklarowane podobnie jak inne metody. Zwyczajowo konstruktory są nazywane Create a destruktory Destroy. Konstruktora używa się do przydzielania zasobów (pamięci, obiektów zagnieżdżonych, itd.) dla klasy oraz do inicjalizowania pól klasy (np. zerowanie pól). Można utworzyć dowolną liczbę konstruktorów ale tylko jeden destruktor. Jeśli klasa posiada kilka konstruktorów, to muszą się one różnić liczbą i/lub typami przekazywanych argumentów. Destruktor służy do zwalniania zasobów, przydzielonych w konstruktorze lub w trakcie działania obiektu danej klasy. Destruktor nie pobiera żadnych argumentów. Do usuwania niepotrzebnych już w programie obiektów, zaleca się stosowanie metody Free, która sama wywołuje destruktor, wcześniej sprawdzając czy obiekt jeszcze istnieje (jeśli obiekt już nie istnieje, to destruktor nie jest wtedy wywoływany). Zapobiega to powstawaniu przypadkowych błędów w programie, związanych z błędnym gospodarowaniem pamięcią używaną przez obiekt (oczywiście o ile destruktor nie zawiera błędów).
Przykład Object
edytujtype Data = object(TObject) Dzien: 1..31; Miesiac: 1..12; Rok: integer; procedure Drukuj; end; procedure Data.Drukuj; begin writeln(Dzien,'.',Miesiac,'.',Rok) end;
Przykład Class
edytujDeklaracja oraz użycie konstruktora i destruktora
type TData = class(TObject) private FDzien: 1..31; FMiesiac: 1..12; FRok: integer; public constructor Create; destructor Destroy; procedure Drukuj; end; constructor TData.Create; begin FDzien := 1; FMiesiac := 5; FRok := 2013; end; destructor TData.Destroy; begin // nic nie robi, bo nie przydzielano klasie żadnych zasobów end; procedure TData.Drukuj; begin Writeln(FDzien, '-', FMiesiac, '-', FRok) end; var Data1: TData; begin Data1 := TData.Create; {...} Data1.Free; end.
Odwołania do klasy
edytujŁącza programowego
edytujTyp wskaźnikowy
edytujWskaźnik zawiera adres zmiennej. Deklaracja zmiennych typu wskaźnikowego zawiera operator ^ przed nazwą typu, na który ma wskazywać. Kiedy chcemy uzyskać adres zmiennej, poprzedzamy ją operatorem @. Kiedy chcemy się odwołać do elementu wskazywanego przez wskaźnik, piszemy po nazwie wskaźnika ^. Można też tworzyć nowe zmienne dynamiczne, np. procedurą new(wskaźnik) i usuwać je, np. procedurą dispose(wskaźnik).
Przykłady:
edytujprogram wsk; var wsk1, wsk2: ^integer; i: integer; begin i := 1; wsk1 := @i; if @wsk1^ = wsk1 then writeln('tak'); {drukuje tak} writeln(wsk1^); {drukuje 1} wsk1^ := 2; wsk1 := nil; if wsk1 = nil then writeln('tak'); {drukuje tak} writeln(i); {drukuje 2} new(wsk2); wsk2^ := 3; writeln(wsk2^); {drukuje 3} dispose(wsk2); new(wsk1); wsk2 := wsk1; wsk1^ := 4; writeln(wsk1^); {drukuje 4} readln; dispose(wsk1); {dispose(wsk2); - to byłby błąd} if wsk2 = nil then writeln('tak'); {nic nie drukuje} readln; end.
Typ proceduralny
edytujTyp wariantowy
edytujZgodność typów
edytujIdentyczność typów
edytujDwa typy a i b są identyczne, jeżeli:
- posiadają ten sam identyfikator typu
- dają się wywieźć od tego samego identyfikatora za pomocą konstrukcji: a=b.
Zgodność operacyjna
edytujDwa typy są zgodne operacyjne, jeśli są m.in.:
- identyczne,
- typami całkowitymi,
- typami rzeczywistymi,
- jeden jest typem okrojonym drugiego,
- są typami okrojonymi tego samego typu bazowego,
- typami zbiorowymi o zgodnych typach bazowych
- jeden jest typem Pointer, a drugi dowolnym typem wskaźnikowym,
- są typami proceduralnymi o identycznych typach wyników, jednakowej liczbie parametrów i identycznych typach odpowiadających sobie parametrów.
Zgodność w sensie przypisania
edytujInstrukcja przypisania z := w jest poprawna, o ile typ a zmiennej z i typ b wyrażenia w spełniają jeden z warunków:
- są typami rzeczywistymi,
- są typami łańcuchowymi,
- a i b są identyczne, ale nie są typami plikowymi, ani nie zawierają odwołań do typu plikowego,
- a i b są zgodnymi typami porządkowymi i wartość w jest jedną z możliwych wartości typu a,
- a jest typem rzeczywistym, a b typem całkowitym,
- a jest typem łańcuchowym, a b jest typem znakowym,
- są zgodnymi operacyjnie typami zbiorowymi,
- są zgodnymi operacyjnie typami wskaźnikowymi,
- są zgodnymi operacyjnie typami proceduralnymi.
Inne podziały typów
edytujPredefiniowalność
edytuj- standardowe – są one predefiniowane i nie wymagają opisu programisty.
- niestandardowe – nie są predefiniowane i muszą być opisane przez programistę.
Uzależnienie od procesora i systemu operacyjnego
edytuj- podstawowe – są niezależne od procesora i systemu operacyjnego.
- ogólne – zależą od procesora i systemu operacyjnego.