 
1
Wykład X
Języki programowania
Object Pascal: Proste typy
danych
Podstawy informatyki
Semestr I Transport
Semestr II Elektrotechnika
 
2
Interesuje nas
wykonywanie algorytmów
przy pomocy komputera
Naszym
największym
zainteresowaniem  są  jednak  objęte 
algorytmy  przeznaczone  do  wykonania 
przez  komputery,  a  zatem  powinniśmy 
poświęcić  nieco  czasu  na  odniesienie 
algorytmów 
do
prawdziwych
komputerów.
 
3
Komputer potrafi zwykle
wykonać niewielką ilość
prostych operacji
Nawet najbardziej wyrafinowany komputer jest w
rzeczywistości tylko ogromną, dobrze zorganizowaną
masą bitów i, co więcej, normalnie potrafi on wykonywać
na nich jedynie niewielką liczbę krańcowo prostych
operacji,
takich
jak
zerowanie,
przerzucanie
i sprawdzanie.
W  jaki  sposób  przedstawiamy  algorytm  prawdziwemu 
komputerowi i jak sprawiamy, że wykonuje on
odpowiedni proces tak, jak to zamierzono?
Powiedzmy  to  jeszcze  bardziej  bezceremonialnie.  Jak 
sprawiamy, że głupia maszyna o tak małych
zdolnościach w imponujący sposób realizuje nasze
subtelne i starannie opracowane algorytmy?
 
4
Algorytmy muszą być
zapisane w jednoznaczny i
formalny sposób
Pierwszym spostrzeżeniem jest to, że nasze algorytmy
muszą być zapisane w jednoznaczny i formalny
sposób. 
Zanim  spróbujemy  zrozumieć,  w  jaki  sposób  obracając 
bitami można wypełnić proste zadanie, np. „przebiegnij
listę, dodając każdą płacę do liczby «na boku»”, musimy
zadanie to dokładnie określić odpowiadając na pytania:
– Gdzie komputer znajdzie tę listę?
– Jak ją przebiegnie?
– Gdzie znajdzie płacę i liczbę ,,na boku”? Itd.
Zadanie „przebiegnij listę” nie jest wcale wiele bardziej
dokładne i jednoznaczne niż „ubijaj białka aż do
spienienia”.
 
5
Języki programowania,
programy, programiści
Aby  opisać  algorytm  na  użytek  komputera, 
posługujemy  się  językiem  programowania,  w 
którym piszemy programy.
Program to oficjalne i formalne wydanie algorytmu, 
nadające się do wykonania przez komputer.
Język  programowania  składa  się  z notacji  i  reguł, 
według których pisze się programy, a osoba pisząca 
program zwie się programistą. (Ta osoba nie musi 
być  autorem  algorytmu,  na  którym  opiera  się 
program.)
 
6
Programy wymagają
precyzyjnej składni
Język programowania wiąże się zwykle ze sztywną składnią,
dopuszczającą używanie jedynie specjalnych kombinacji wybranych
symboli i słów kluczowych.
Każda próba nadużycia tej składni może okazać się fatalna: jeśli np. 
napisze się wczytaj X w języku, którego instrukcje wczytywania są
postaci
wprowadź
X,
możliwe,
że
wynikiem
będzie
bezceremonialne BŁĄD SKŁADNIOWY E5414 W WIERSZU 108. To
oczywiście wyklucza nawet tak uprzejme, ale nieprecyzyjne
żądania, jak „proszę wczytać wartość X z wejścia”.
To prawda,  że  uprzejme,  obszerne  instrukcje  są  przyjemniejsze  dla 
ludzi i być może są dla nich bardziej jednoznaczne niż ich zwięzłe i
bezosobowe odpowiedniki; jest także prawdą, że chcielibyśmy, aby
komputery były tak przychylne użytkownikowi, jak to tylko jest
możliwe. Jednakże trzeba przeciwstawić te fakty aktualnemu
brakowi zdolności rozumienia przez komputery swobodnie
mówionego (lub pisanego) języka naturalnego.
 
7
Co zawiera formalna
składnia języka
programowania ?
Formalna składnia typowego języka programowania
zawiera:
– systematyczne warianty kilku struktur sterujących,
– systematyczne  sposoby  definiowania  rozmaitych 
struktur danych
– systematyczne wzorce podstawowych instrukcji. 
Muszą  one  należeć  do  zbioru  dopuszczalnych 
instrukcji stosowanego języka programowania,
ponieważ komputer nie wykona żadnej instrukcji,
nawet najbardziej jasnej i jednoznacznej, jeśli nie ma
jej wśród tych, które dopuszcza dany język.
 
8
Przykład
Algorytm sumowania liczb
od 1 do N
W typowym (hipotetycznym)
języku
programowania
JP
można
by
zapisać,
jak
następuje:
wczytaj N;
X:=0;
dla Y od 1 do N wykonaj
X:=X+Y
koniec; wypisz X.
X:=0
jest
instrukcją
przypisania, która nadaje
zmiennej
X
wartość
początkową 0 (w algorytmach
zapisywaliśmy ją jako X←0).
Zwróć uwagę na słowa kluczowe
zapisane grubszą czcionką; są one
częścią składni JP
Oznacza  to,  że  formalna  definicja 
składni
najprawdopodobniej
zawiera klauzulę stwierdzającą, że
jednym z poprawnych rodzajów
instrukcji w tym języku jest
instrukcja-dla,
której
ogólny
wzorzec składa się ze słowa
kluczowego
dla,
po
czym
następuje poprawny nagłówek-
dla, po czym następuje wykonaj,
po czym następuje poprawna
instrukcja, po czym następuje
koniec
 
9
Notacja BNF (Backus-Naur
Form, od nazwisk
wynalazców)
Definicje składni można zapisać symbolicznie w notacji
zwanej BNF w następujący sposób (,,|” oznacza ,,lub”):
<instrukcja>:<instrukcja-dla>|<instrukcja-
przypisania>|...
<instrukcja-dla>: 
dla <nagłówek-dla>
wykonaj
<instrukcja> koniec
Opis klauzuli nagłówka mógłby brzmieć:
<nagłówek-dla>: <zmienna> od <wartość> do
<wartość>
<wartość> można wtedy określić jako zmienną, jawnie
podaną liczbę lub jakiś inny obiekt.
 
10
Schematyczny sposób
przedstawiania reguł
składniowych
 
11
Schematyczny sposób
przedstawiania reguł
składniowych
 
12
Podobnie są narzucane
wzorce definiowania
struktur danych
Np. tablicę TA o wymiarach 50 na 100, której wartości
mogą być liczbami całkowitymi, można by zdefiniować
w hipotetycznym języku JP instrukcją
definiuj TA tablica [1..50, 8..107] w niej liczby
całkowite
a język mógłby dopuścić odwołania do elementów
tablicy TA wyrażeniami postaci
TA(wartość, wartość)
Zauważ, jak określiliśmy nie tylko wymiary TA, lecz
także jej wartości indeksów; wiersze tablicy
ponumerowano 1, 2, ..., 50, ale jej kolumnom (z
jakiegoś powodu) nadano numery 8, 9, ..., 107.
 
13
Składnia wyznacza
znacznie więcej
W rzeczywistości składnia wyznacza znacznie
więcej niż tylko dostępne struktury sterujące i
struktury danych oraz operacje elementarne.
Zwykle  język  ma  sztywne  reguły  nawet  w  tak 
drobnych kwestiach, jak poprawne ciągi symboli,
których można używać do nazywania zmiennych
lub struktur danych, i maksymalna liczba cyfr
dopuszczalna w wartościach numerycznych.
Niektóre 
języki
ograniczają
długości
nazw
zmiennych do najwyżej, powiedzmy, ośmiu
symboli, z których pierwszy ma być literą alfabetu.
 
14
Ważna jest także sprawa
interpunkcji
W językach programowania nie należy do rzadkości 
wymaganie,  aby  po  pewnych  rodzajach  instrukcji 
następował  średnik,  a  po  innych  -  odstęp,  aby 
komentarze były ujęte w specjalne nawiasy, itd.
Biada  tym,  którzy  do  tych  wymagań  się  nie 
zastosują  (dopadnie  ich  zapewne  „choroba 
średnika”).
Niedługo  poznamy  szczegółowy  opis  składni 
konkretnego  języka  programowania,  z  regułami 
stosowania średników i całą resztą.
 
15
Programy wymagają
precyzyjnej semantyki
Wyposażenie języka w precyzyjną składnię stanowi
tylko część zadania stojącego przed projektantem
języka programowania.
Bez formalnej i jednoznacznej semantyki a więc bez 
znaczenia
każdego
wyrażenia
dozwolonego
składniowo, składnia jest niemal bezwartościowa.
Gdyby  nie  podano  znaczenia  instrukcji,  w  naszym 
hipotetycznym języku JP taki oto fragment programu
dla Y od 1 do N wykonaj
mógłby, oznaczać „odejmij Y od 1 i zapamiętaj wynik
w N”.
 
16
Bez reguł semantycznych
nie poznamy
przeznaczenia instrukcji
Co gorsza, któż powiedział, że słowa kluczowe dla,
od, do itp. mają mieć coś wspólnego z ich
znaczeniem w konwencjonalnej polszczyźnie?
A może ten sam fragment programu oznacza „wyzeruj 
całą pamięć komputera, zmień wartości wszystkich
zmiennych na 0, wypisz »DO DIABŁA Z JĘZYKAMI
PROGRAMOWANIA« i zatrzymaj się!”?
Któż  powiedział,  że  „:=”  oznacza  „przypisz”  i  że  „+” 
oznacza „plus”? Któż powiedział, że instrukcje
wykonuje się w takiej kolejności, w jakiej są napisane?
A może „;” oznacza „po wykonaniu tego, co
następuje”, nie zaś ,,a potem wykonaj, co następuje”?
 
17
Na szczęście w językach
znaczenia symboli są podobne do
znaczeń w języku angielskim
Oczywiście moglibyśmy odgadnąć, co to oznacza,
ponieważ projektant języka JP tak dobrał zapewne słowa
kluczowe i symbole specjalne, aby ich znaczenia były
możliwie najbardziej zbliżone do ogólnie przyjętych.
Ale komputer na podstawie takich przypuszczeń działać 
nie może. Gdyby nawet mógł w jakiś sposób
wywnioskować konwencjonalne znaczenie słów i takich
symboli, jak „+”, skąd wiedziałby, bez wyraźnego
pouczenia, co zrobić z nagłówkiem pętli
dla Y od 1 do N wykonaj
gdy wartością N jest powiedzmy -314.1592?
 
18
W poznawaniu składni i
semantyki języka wspiera
nas dokumentacja
Wydaje
się
zatem
jasne,
że
język
programowania  wymaga  nie  tylko  sztywnych 
reguł 
definiowania
postaci
poprawnego
programu,  ale  także  równie  sztywnych  reguł 
definiowania jego znaczenia.
Projektanci  i  producenci  dostarczają  jednak 
szczegółową  dokumentację  języka,  całe  jej 
tomy.  Te  podręczniki  języka  zawierają 
bogactwo  informacji  dotyczących  zarówno 
składni, jak i semantyki.
 
19
Przystępujemy do
kodowania
Mamy zatem język programowania JP, składnię,
semantykę i całą resztę, i właśnie skończyliśmy
opracowywanie algorytmu A rozwiązania pewnego
zadania algorytmicznego.
Przystępujemy  teraz  do  zaprogramowania  tego 
algorytmu w języku JP, czynności określanej niekiedy
jako kodowanie A w JP, i chcemy przedstawić
powstały program, nazwijmy go A
P
naszemu
komputerowi.
Cóż dzieje się dalej? Odpowiedź brzmi, że w zasadzie 
istnieją dwie możliwości, zależnie od tego, jakiego
języka i komputera użyjemy.
 
20
Od algorytmu do języka
maszynowego
Program A
P
możemy wprowadzić do pamięci komputera
wystukując go na klawiaturze, wczytując z urządzenia
takiego jak dysk, odbierając z innego komputera za
pośrednictwem elektronicznego kanału komunikacyjnego lub
w jakiś inny sposób (same nośniki fizyczne i sposób ich
używania, nas tutaj nie interesują, w przeciwieństwie do
tego, co dzieje się potem).
Program  A
P
przechodzi pewną liczbę przekształceń, które
stopniowo sprowadzają go „w dół” do poziomu, na którym
komputer już może sobie poradzić. Ostatecznym wynikiem
tych przekształceń jest program A
M
na poziomie maszyny
(mówi się o nim również, że jest napisany w języku
maszyny), gdyż już teraz komputer „rozumie” jego operacje
podstawowe, takie jak instrukcje manipulowania bitami.
 
21
Języki programowania
wysokiego poziomu
Liczba przekształceń bywa różna, zależnie od języka i
komputera, ale najczęściej jest ich od dwóch do czterech. 
Obiektami pośrednimi  są zwykle poprawne programy  w coraz 
to prymitywniejszych językach programowania. Ich repertuar
struktur sterujących i struktur danych stopniowo, podobnie jak
instrukcji podstawowych, staje się coraz skromniejszy, aż
wreszcie
pozostają
jedynie
najbardziej
elementarne
możliwości działania na bitach.
Dopiero po tej ostatecznej fazie przekształceń komputer może 
uruchomić (lub wykonać) pierwotny program A
M
.
Jest już dla nas teraz oczywiste, dlaczego języki takiego
rodzaju jak ten, w którym napisano pierwotny program
użytkownika A
P
, nazywają się językami programowania
wysokiego poziomu
 
22
Przypomina to
podprogramy
Przekształcenia,
o
których
mówiliśmy
przypominają  nieco  zastępowanie  procedur  ich 
treścią.
Na 
instrukcję
w
języku
programowania
wysokiego  poziomu  można  patrzeć  jak  na 
wywołanie  podprogramu  lub  jak  na  instrukcję 
podstawową,  która  jednak  dla  komputera  nie 
jest dostatecznie podstawowa.
W  konsekwencji  trzeba  ją  uściślić  i  sprowadzić 
do poziomu kompetencji komputera.
 
23
Kompilacja, asembler
Pomówmy o pierwszym przekształceniu, zwanym kompilacją, w
którym program wysokiego poziomu A
P
zostaje przetłumaczony
na program A
S
w języku niższego poziomu, zwanym językiem
adresów symbolicznych lub asemblerem.
Języki adresów symbolicznych różnią się dla różnych maszyn, ale 
z reguły stosuje się w nich dość proste struktury sterujące,
przypominające instrukcje skocz oraz konstrukcje jeśli-to;
operują nie tylko bitami, lecz także liczbami całkowitymi i
ciągami symboli.
Mogą  one  odwoływać  się  bezpośrednio  do  adresów  w  pamięci 
komputera (ogromnego obszaru zawierającego całe stosy bitów),
mogą odczytywać spod tych adresów wszelkie zakodowane
liczby i napisy, i mogą tamże zapamiętywać kody liczb i napisów.
 
24
Przykład (hipotetycznego)
asemblera
Typową konstrukcję pętli wysokiego poziomu:
dla Y od 1 do N wykonaj
   <treść pętli>  koniec
można przetłumaczyć na jej odpowiednik w języku adresów
symbolicznych:
LDS 0,Y
(załaduj stałą 0 pod adres Y)
PĘTLA POR N, Y
(porównaj wartości pod adresami N i Y)
SKR RESZTA(jeśli równe, skocz do instrukcji o etykiecie RESZTA)
DDS 1,Y
(dodaj stałą 1 do wartości pod adresem Y)
    <przetłumaczona treść pętli>
SKO PETLA (skocz z powrotem do instrukcji o etykiecie PĘTLA)
RESZTA
(reszta programu)
 
Przekształcanie
programu
wysokiego
poziomu na kod
maszynowy
Proces kompilacji, tłumaczący
programy
komputerowe
wysokiego poziomu na język
adresów symbolicznych sam
jest również wykonywany przez
program
komputerowy
(kompilator)
Proces 
przekształcania
na
niższy
poziom,
w
którym
kompilacja jest pierwszą i
najbardziej
zawiłą
częścią,
ilustruje rys.
Pozostałe 
kroki
tłumaczą
asembler na język maszynowy.
 
26
Oprogramowanie
systemowe
Warto zaznaczyć, że kompilatory różnych języków
wysokiego poziomu, jakie obsługuje dany komputer,
często (choć nie zawsze) należą do dużej grupy różnych
programów dostarczanych przez producenta (komputera
bądź
systemu
operacyjnego),
zwykle
zwanych
oprogramowaniem systemowym.
Ich  ogólną  rolą  jest  ułatwianie  współpracy  z  komputerem 
na wysokim poziomie i jednoczesne odgrodzenie
użytkownika od wielu szczegółów niskiego poziomu
związanych z trybem współpracy, np. uruchomieniem
programów
napisanych
przez
użytkownika,
komunikowaniem się z innymi komputerami, sprzęganiem
się ze specjalnym wyposażeniem zewnętrznym...
 
27
Interpretatory i
natychmiastowe
wykonanie
Jest jeszcze inny sposób, w jaki komputery wykonują
przedstawione im programy, który nie obejmuje
tłumaczenia całego programu na język niższego poziomu.
Każda 
z instrukcji
wysokiego
poziomu
zostaje
przetłumaczona
na
instrukcje
poziomu
maszyny
natychmiast po jej napotkaniu, a te z kolei od razu się
wykonuje. W pewnym sensie interpreter pełni rolę
„pseudoprocesora” wykonując instrukcje wysokiego
poziomu jedną po drugiej, dokładnie tak, jak są podane. 
Mechanizm  odpowiedzialny  za  to  lokalne  tłumaczenie  i 
natychmiastowe
wykonanie
jest
też
fragmentem
oprogramowania
systemowego,
nazywanym
interpretatorem (interpreterem).
 
28
Zalety i wady
interpretowania
programów
Podejście interpretacyjne ma pewne oczywiste zalety, m.in.
zwykle łatwiej napisać byle jaki, ale użyteczny
interpretator niż sensowny kompilator;
wykonywanie  prowadzone  przez  interpretator  pozwala  na 
łatwiejsze śledzenie i podsumowanie wykonania programu.
Są jednak cechy interpretacji niekorzystne w stosunku do
kompilacji
nie ma zwartego pliku wykonywalnego
trzeba  rozpowszechniać  kod  źródłowy  (trudno  ochronić 
prawa autorskie)
wolniejsze  wykonanie  (każdorazowo  trzeba  dokonywać 
interpretacji)
 
29
Kompilować czy
interpretować ?
To,  czy  komputer  będzie  kompilował,  czy 
interpretował  dany  program,  zależy  od 
przeznaczenia  danego  programu,  samego 
komputera, 
języka
programowania,
i
konkretnego
pakietu
oprogramowania
systemowego, którego używamy.
Niektóre  języki  programowania  nadają  się  do 
interpretowania  bardziej  niż  inne,  wszystkie 
jednak mogą w zasadzie być kompilowane.
 
30
Dlaczego nie
algorytmiczne Esperanto?
Od czasu, gdy we wczesnych latach pięćdziesiątych
zaczęły
pojawiać się języki programowania
wysokiego poziomu, zaprojektowano ich setki oraz
napisano dla nich kompilatory i (lub) interpretatory,
a nadal nowe języki pojawiają się jak grzyby po
deszczu.
Dlaczego?  Czynie  byłoby  lepiej  mieć  jeden  język 
uniwersalny, takie algorytmiczne Esperanto, w
którym zapisywałoby się wszystkie algorytmy i
którego każdy mógłby się łatwo nauczyć? Skąd
taka mnogość języków? Czym się różnią ? Kto
używa których języków i w jakich celach?
 
31
Dlaczego nie
algorytmiczne Esperanto?
Odpowiedź
Zasadniczo są dwie przyczyny tego zjawiska:
– nowe osiągnięcia sprzętowe (choć dziś w dużej
mierze  udaje  się  uwolnić  wiele  języków  od 
bezpośredniego, ścisłego związku ze sprzętem).
– oraz nowe i zróżnicowane dziedziny zastosowań
;
Obie  stwarzają  zapotrzebowanie  na  nowe  języki 
programowania. 
Badania
nad
językami
programowania  należą  do  z  najbardziej  się 
rozwijających  i przyciągających  powszechną  uwagę 
dziedzin informatyki.
 
32
Badania nad językami
programowania
Ludzie chcą języków zarówno uniwersalnych, jak i przeznaczonych
do szczególnych zastosowań oraz ich precyzyjnej definicji i sprawnej
realizacji.
Wymyśla się wyrafinowane techniki kompilacji i tłumaczenia, proponuje 
się nowe struktury sterujące i nowe struktury danych oraz wprowadza
się silne mechanizmy umożliwiające programistom definiowanie ich
własnych struktur danych.
Pożądane  są  języki  zachęcające  do  dobrego  stylu  programowania 
i wszyscy próbują zaprojektować je tak, aby zawrzeć w nich rozmaite
zalecane idee budowy algorytmów.
Badacze 
interesują
się
opracowaniem
środowisk
programistycznych, czyli przychylnych użytkownikowi systemów
konwersacyjnych, pozwalających programiście pisać, redagować,
zmieniać, wykonywać, analizować, poprawiać i symulować programy.
Fascynujące  badania  dotyczą  wizualnych  języków  programowania, 
umożliwiających rysowanie programów zamiast ich pisania.
 
33
Uniwersalność języków
programowania
Ostatnia nasza uwaga dotyczy uniwersalności języków
programowania.
W pewnym technicznym sensie praktycznie wszystkie języki 
programowania są równoważne pod względem swojej siły
wyrazu. Każde zadanie algorytmiczne rozwiązywalne w
jednym języku jest w zasadzie rozwiązywalne również w
każdym innym języku.
Różnice  między  językami  są  pragmatyczne  i  dotyczą 
przydatności do pewnych, zastosowań, przejrzystości,
struktury, sprawności realizacji i algorytmicznych sposobów
myślenia.
Wobec  znaczących  różnic  między  językami  programowania 
ten fakt może być przyjmowany jako coś niespodziewanego.
 
34
Wybór języka
programowania
W tym miejscu rozpoczniemy kursu jednego
z języków programowania: Object Pascala
(czy jeśli ktoś woli Delphi dla Windows).
Pisanie  programów  w  tym  języku  będzie 
podstawowym
elementem
ćwiczeń
realizowanych
na
laboratorium
(w
następnym semestrze).
Dziś  poznamy  jedynie  podstawowe  typy 
danych języka Object Pascal.
 
35
Po co są typy danych ?
O znaczeniu właściwej reprezentacji reprezentacji
danych mówiliśmy wiele wcześniej (wykład 2 i 8-9).
W  matematyce zmienne  klasyfikuje  się  zgodnie  z ich pewnymi 
istotnymi właściwościami.
Rozróżnia się zmienne rzeczywiste, zespolone i logiczne lub też 
zmienne reprezentujące pojedyncze wartości, zbiory wartości,
zbiory zbiorów, a także funkcje, funkcjonały, zbiory funkcji, itd.
W  przetwarzaniu  danych  klasyfikacja  zmiennych  jest  pojęciem 
równie ważnym (jeśli nie ważniejszym).
Każda  stała,  zmienna,  wyrażenie,  czy  funkcja  jest 
pewnego typu.
Typ  ten  dokładnie  charakteryzuje  zbiór  wartości,  do  którego 
może należeć stała, bądź jakie może przyjmować zmienna czy
wyrażenie, bądź jakie mogą być generowane przez funkcję.
 
36
Cechy charakterystyczne
pojęcia typu
Typ danych określa zbiór wartości, do którego należy stała
bądź które może przyjmować zmienna lub wyrażenie albo
które mogą być generowane przez operator lub funkcję.
Typ  wartości  oznaczonej  przez  stałą,  zmienną  lub  wyrażenie 
można określić na podstawie ich postaci bądź deklaracji , bez
konieczności wykonywania procesu obliczeniowego.
Każdy  operator  lub  funkcja  ma  argumenty  ustalonego  typu, 
jak również daje wynik ustalonego typu. Jeśli operator
dopuszcza argumenty wielu typów (np. „+” oznacza
dodawanie zarówno liczb całkowitych jak i rzeczywistych), to
typ uzyskiwanego wyniku jest określany za pomocą
specyficznych dla danego języka reguł.
 
37
Typy nadają monotonnym
bitom interpretację
W konsekwencji kompilator może korzystać z informacji o typach
w celu sprawdzenia poprawności wielu konstrukcji.
Na  przykład  przypisanie  wartości  logicznej  (prawda-fałsz)  do 
zmiennej arytmetycznej (liczba) może zostać wykryte bez
potrzeby wykonywania programu, na etapie jego kompilacji.
Ten  rodzaj  redundancji  w  tekście  programu  jest  niezwykle 
pomocny przy tworzeniu programów i należy go uznać za
podstawową zaletę dobrych języków programowania wysokiego
poziomu (w stosunku do kodu maszynowego czy też kodu
adresów symbolicznych).
Ostatecznie dane w pamięci będą stanowiły jednolitą masę bitów 
bez jakiejkolwiek struktury. Jednakże to właśnie ta struktura
abstrakcyjna umożliwia programistom rozpoznawać znaczenie
danych w monotonnym krajobrazie pamięci maszyny.
 
38
Moc typu
Liczbę  różnych  wartości  należących 
do  typu  T  nazywa  się  mocą 
(cardinality) T.
Moc  typu  pozwala  określić  wielkość 
pamięci 
potrzebnej
do
reprezentowania zmiennej x typu T.
 
39
Typy standardowe
Ze
względu
na
znaczenie
reprezentacji
informacji
programiści
mają
możność
definiowania nowych typów danych.
Oprócz  typów  definiowanych  przez  programistę 
muszą  istnieć  pewne  typy  standardowe 
(standard 
types),
które
są
zdefiniowane
wcześniej (przez producenta kompilatora).
W  Object    Pascalu  typy  standardowe  zawierają 
m.in.    liczby,  wartości  logiczne,  znaki  i 
łańcuchy tekstowe (ciągi znaków).
 
40
Klasyfikacja
najważniejszych typów
danych w Object Pascalu
Typy proste
– Typy porządkowe
• Typ
wyliczeniowy
• Typy logiczne
• Typy całkowite
• Typ znakowy
• Typy okrojone
– Typy rzeczywiste
– Typy łańcuchowe
Typy strukturalne
– Typy tablicowe
– Typ rekordowy
– Typ zbiorowy
– Typ plikowy
Typy wariantowe
Typy wskaźnikowe
Typy proceduralne
Typ obiektowy
 
41
Typ logiczny
Dwie  wartości  standardowego  typu  logicznego  są 
najczęściej  oznaczane  identyfikatorami  false  i 
true.
Do  operatorów  logicznych  zaliczamy  koniunkcję 
(,  and,  iloczyn  logiczny),  alternatywę  (,  or, 
sumę logiczną) i negację (~, not).
p
q
pq
pq
~p
true
true
true
true
false
true
false
true
false
false
false
true
true
false
true
false
false
false
false
true
 
42
Porównania dają wyniki typu
logicznego
Zauważmy,
że
zastosowanie
operatora
porównania daje wynik typu logicznego.
W związku z tym wynik porównania może być 
przypisany do zmiennej logicznej  bądź użyty 
jako argument operatora logicznego.
Np.  dla  zmiennych  p  i  q  typu  logicznego  i   
zmiennych całkowitych x=5, y=8, z=10 dwie 
instrukcje  przypisania:  p:=x=y  i  q:=(x<y)   
(yz) dają w rezultacie p=false i q=true.
 
43
Typy logiczne w Object
Pascalu
Przedstawione typy różnią się pomiędzy sobą sposobem
reprezentacji danych w pamięci operacyjnej.
Typ
Rozmiar [B]
Boolean
ByteBool
1
WordBool
2
BOOL, LongBool
4
 
44
Typ całkowity
Typ Integer (podstawowy z typów całkowitych) 
stanowi  podzbiór  wszystkich  liczb  całkowitych, 
którego  zakres  zależy  od  możliwości  danej 
maszyny.
Jednakże  zakłada  się,  że  wszystkie  operacje  na 
danych  tego  typu  są  dokładne  i  odpowiadają 
podstawowym  prawom  arytmetyki  oraz,  że 
wykonanie  programu  zostanie  przerwane  jeśli 
wynik  znajdzie  się  poza  reprezentowanym 
podzbiorem.
 
45
Działania na danych typu
całkowitego
Standardowe  operatory  dostarczają  tu  czterech 
podstawowych 
operacji:
dodawania
(+),
odejmowania (-), mnożenia (*) i dzielenia (div)
Wprowadza  się  też  operację  „modulo”  (w  Pascalu 
mod)  spełniającą  równość  (m  div  n)*n+(m  mod 
n)=m. Wobec tego m div n stanowi całkowitą część 
tego  ilorazu,  natomiast  m  mod  n  stanowi  resztę  z 
tego ilorazu.
Podobnie  operatory  działają  dla  pozostałych  typów 
całkowitych dostępnych w językach programowania.
 
46
Typy całkowite w Object
Pascalu
Typ
Zakres
Rozmiar
[B]
Rozmia
r [b]
ShortInt
-128..127 (-2
7
..2
7
-
1)
1
8
Byte
0..255 (0..2
8
-1)
1
8
SmallInt
-32768..32767(-
2
15..
2
15
-1)
2
16
Word
0..65535 (0..2
16
-1)
2
16
Integer, 
LongInt
-
2147483648..214
7483647
(-2
31
..2
31
-1)
4
32
Cardinal, 
LongWord
0..2
32
-1
4
32
Int64, 
Comp
*
-2
63
.. 2
63
-1
8
64
 
47
Typ rzeczywisty
Oznacza pewien podzbiór liczb rzeczywistych. Podczas
gdy zakłada się, że arytmetyka liczb całkowitych daje
wyniki dokładne, to dla arytmetyki liczb rzeczywistych
dopuszcza się wyniki niedokładne w ramach pewnych
błędów zaokrąglenia spowodowanych wykonywaniem
obliczeń na skończonej licznie cyfr.
Jest  to  zasadniczy  powód  dla  którego  w  większości 
języków programowania wyraźnie odróżnia się typy
całkowite i rzeczywiste.
Oferowany  zestaw  działań  jest  tożsamy  z  zestawem 
zdefiniowanym dla liczb całkowitych, z tym że dzielenie
oznacza  się  symbolem  /  oznaczającym  dzielenie 
zwracające wartość rzeczywistą
.
 
48
Typy rzeczywiste w Object
Pascalu
Typ
Rozdzielczość..Z
akres***
Liczba
cyfr
znaczącyc
h****
Rozm
iar
[B]
Single
1.510
-45
..3.410
38
7-8
4
Real48
*
2.910
-39
..1.710
38
11-12
6
Double,
Real
5.010
-
324
..1.710
308
15-16
8
Extended
3.610
-
4951
..1.110
4932
19-20
10
Currency
**
-
922337203685477
.5808..
922337203685477
.5807
19-20
8
 
49
Typ znakowy
Obejmuje zbiór znaków alfanumerycznych.
Niestety  jak  mówiliśmy  na  wcześniejszych  wykładach 
nie istnieje ogólnie przyjęty standardowy zbiór znaków
stosowany we wszystkich systemach komputerowych.
Typ  znakowy  domyślnie  reprezentuje  obecnie  dane  z 
kodu właściwego dla języka systemu operacyjnego
kodu ANSI. Nie należy jednak tego uznawać za
niezmiennik
i
sposób
kodowania
zależy
od
konkretnego komputera i zainstalowanego na nim
systemu operacyjnego, a nawet od stosowanego
oprogramowania (możemy np. stosować znaki
standardu UNICODE).
 
50
Założenia dotyczące
zbioru znaków
Aby konstruować niezależne od komputera algorytmy, w
których korzysta się ze znaków musimy przyjąć pewne
założenia dotyczące typu znakowego:
Zawiera znaki łacińskie, cyfry arabskie i pewną liczbę innych 
znaków graficznych, jak np. znaki przystankowe.
Podzbiory liter i cyfr są uporządkowane i spójne, tzn.
– (‘A’x)  (x‘Z’)x jest literą
– (‘0’x)  (x‘9’)x jest cyfrą
Zawiera znak pusty (spację), którego można używać jako
separatora.
W  większości  języków  wprowadza  się  wzajemnie  odwrotne 
funkcje pozwalające dokonywać konwersji typu znakowego
na całkowity i odwrotnie.
 
51
Typy znakowe w Object
Pascalu
Do oznaczenia typu znakowego służą predefiniowane
identyfikatory Char, ANSIChar, WideChar. Elementami
typu znakowego są znaki ANSI (Char, ANSIChar) lub
UNICODE (WideChar), z których każdy jest pamiętany w
jednym (Char, ANSIChar) lub na dwóch bajtach pamięci
(WideChar).
CHAR
ANSIChar
WideChar
Przykłady wartości typu znakowego:
’A’
’1’
#65 ^H
#$21’ß’
 
52
Typy łańcuchowe
Typy łańcuchowe służą do reprezentowania ciągu znaków.
Definicja może zawierać (lub nie) ograniczenie długości
ciągu znaków. Podstawowym typem łańcuchowym w
Object Pascalu jest
String, ANSIString ShortString
String [rozmiar] 
ShortString[rozmiar]
gdzie rozmiar jest liczbą typu Byte. Brak
wyspecyfikowania rozmiaru powoduje, że rozmiar jest
zależny od długości przechowywanego tekstu (String,
ANSIString do 2 gigabajtów tekstu -wartość maksymalna,
zalecany format) lub dla typu ShortString jest stała i
wynosi 255 znaków.
Istnieje odpowiednio typ WideString (UNICODE)
 
53
Przykłady łańcuchów
tekstowych
’Object Pascal jest jednym z języków 
programowania’
‘Kepler’’s law’
’’’’
^H (Ctrl-H)
#127 (znak Del)
#$7F (znak Del)
’Delphio’#$8^M
 
54
Definiowanie własnych
typów danych w Object
Pascalu
Lokowane  jest  w  części  nagłówkowej 
programu 
bądź
podprogramu
(ich
struktura  zostanie  przedstawiona  na 
następnych wykładach)
Składnia
type sekwencja-definicji-typów
gdzie każda definicja typu ma postać
identyfikator-typu=opis-typu;
 
55
Typy wyliczeniowe
Najprostszą  narzucająca  się  metoda 
definicji  nowego  typu  danych  polega  na 
wyliczeniu wartości tworzących typ.
Np.  w  programie  dotyczącym  figur 
geometrycznych  można  określić  typ 
prosty o nazwie kształt, którego wartości 
mogą  być  oznaczone  identyfikatorami 
prostokąt, kwadrat, elipsa, okrąg.
 
56
Typy wyliczeniowe
(enumerated)
W wielu programach stosuje się liczby
całkowite wtedy, gdy właściwości numeryczne
nie są potrzebne, a liczba całkowita
reprezentuje wybór spośród pewnej małej
liczby wartości.
W  tych  wypadkach  dobrze  jest  wprowadzić 
nowy prosty typ danych T, wyliczając zbiór
wszystkich możliwych wartości c
1
, c
2
, ..., c
n
.
T=(c
1
, c
2
, ..., c
n
)
Mocą typu T jest wartość funkcji moc(T)=n .
 
57
Przykłady typów
wyliczeniowych
kształt=(prostokąt, kwadrat, elipsa, okrąg)
kolor=(czerwony, żółty zielony)
płeć=(mężczyzna, kobieta)
Boolean=(false, true)
dzieńtygodnia=(poniedziałek,  wtorek,  środa,  czwartek,  piątek, 
sobota, niedziela)
waluta=(euro, funt, dolar, korona, rubel, jen)
przeznaczenie=(piekło, czyściec, niebo)
środeklokomocji=(pociąg, autobus, samochód, statek, samolot)
ranga=(szeregowiec, kapral, sierżant, porucznik, major, pułkownik, 
generał)
obiekt=(stała, typ, zmienna, procedura, funkcja)
struktura=(plik, tablica, rekord, zbiór)
 
58
Typy wyliczeniowe
są bardziej obrazowe
Definicja typu wyliczeniowego wprowadza nie tylko nowy
identyfikator typu, ale jednocześnie zbiór identyfikatorów
oznaczających poszczególne wartości definiowanego typu.
Identyfikatorów  tych  można  używać  w  programie  jako 
stałych, a ich wystąpienia czynią program bardziej
zrozumiałym.
Wprowadźmy na przykład zmienne r: ranga czy p: płeć.
Możliwe wówczas są przypisania p:=mężczyzna; r:=major.
Są  one  bardziej  obrazowe  niż  ich  numeryczne  odpowiedniki 
p:=0; r:=4 oparte na założeniu, że do oznaczeń używamy
liczb naturalnych według kolejności ich wyliczania.
 
59
Uporządkowanie w typach
wyliczeniowych
Ponadto translator może dzięki temu
wykrywać „nierozważne” stosowanie
operatorów do typów nienumerycznych
np. p:=p+1;
Wprowadza  się  jednak  operatory  funkcji 
generujących
następnik
bądź
poprzednik argumentu.
Uporządkowanie 
wartości
typu
te
określa następująca reguła (c
i
<c
j
)
(i<j)
 
60
Typy okrojone
Często się zdarza, że zmienna przyjmuje wartości
jedynie z pewnego przedziału wartości określonego
typu.
Wyraża  się  to  definiując  typ  okrojony,  zgodnie  z 
formatem T=min..max, gdzie min i max stanowią
granice przedziału.
Przykłady
rok=1900..2099
litera=‘A’..’Z’
cyfra=‘0’..’9’
oficer=porucznik..generał
 
61
(nie) Dozwolone użycie
typu okrojonego
Dla zmiennych y: rok i L: Litera
– dozwolone  są  przypisania  y:=1973  i 
L:=‘W’
– natomiast
niedozwolone
y:=1291
i
L:=‘9’.
Dopuszczalność  przypisań  y:=i  czy  L:=c, 
gdzie  i  jest  liczbą  całkowitą,  a  c  wartością 
znakową  można  sprawdzić  dopiero  podczas 
wykonania programu.