Grundlagen der Informatik (B) - PD Dr. Stefan Bosse – Universität

Werbung
Grundlagen der Informatik (B)
Einführung Modul Software
Dr. Stefan Bosse
Universität Bremen
Vorlesung WS 2006 / SS 2007 (V070521)
Betriebssysteme
➤ Ein Betriebssystem ist ein Programm, welches von einem Rechner ausgeführt wird.
➤ Dieses Programm wird beim Einschalten eines Rechners (automatisch) gestartet.
➤ Ein Betriebssystem ist sinnvoll, aber nicht notwendig (Microcontroller und eingebettete Systeme können hier Ausnahmen bilden).
➤ Ein Betriebssystem ist eine Organisations- und Verwaltungsstruktur.
➤ Es erfüllt folgende Aufgaben:
Abstraktion
Technische Einzelheiten des Rechners werden vom Betriebssystem gekapselt, so daß
sie
1. weder vom Bediener, noch
2. vom Anwendungsprogrammierer sichtbar sind.
Beispiel für technische Einzelheiten:
1. Ansteuerung von Ein-/Ausgabe-Schnittstellen
2. Grafik-Bildschirm-Steuerung
3. Zugriff auf Speichermedien
Dr. Stefan Bosse •
Seite 1
Grundlagen der Informatik (B)
Betriebssysteme (II)
Plattform für Anwendungsprogramme
Das Betriebssystem definiert eine Menge von Operationen und Funtionen, auf die Anwendungsprogramme zugreifen können.
➥ Sog. Programmierschnittstelle oder API (Application Programming Interface)
➥ Z.B. Lesen und Schreiben von Daten auf Festplattenspeichern.
Typische Abstraktionen sind
1. die Datei als Speicherobjekt, und
2. der Prozeß als Ausführungsobjekt.
Durch Abstraktion werden Anwendungsprogramme unabhängig vond er verwendeten
Rechner-Architektur.
Koordination und Zuteilung von Betriebsmitteln
Prozessorkapazität bei nebenläufigen (parallelen) Mehrprozeß-Betrieb; Ablaufplanung
Seite 2
(Scheduler)
Hauptspeicher ➽ Speichersegementierung
Sekundärspeicher ➽ Dateisystem
Zugriffsrechte aus Ein-/Ausgabe-Einheiten ➽ Mehrbenutzer-Betrieb
Schutz mehrere gliechzeitig oder nacheinander aktiver Benutzer ➽ MehrbenutzerBetrieb
Dr. Stefan Bosse •
Grundlagen der Informatik (B)
Betriebssysteme (III)
Seite 3
Dr. Stefan Bosse •
Grundlagen der Informatik (B)
Betriebssysteme (IV)
Bedienschnittstellen
KommandoInterpreter
Grafische
Bedienschnittstelle (Oberfläche)
Seite 4
Dr. Stefan Bosse •
Grundlagen der Informatik (B)
Prozesse
➤ Ein Prozeß ist der Ablauf eines sequenziellen Programms in einer Rechneranlage. Das Programm besteht aus Maschinenbefehlen, die als lineare Liste sequenziell abgearbeitet werden.
➤ Ein Programm stellt eine [statische] Handlungsvorschrift dar.
Diese gibt an, wie Daten verarbeitet oder Berechnungen durchgeführt werden sollen.
➤ Ein Prozeß ist hingegen durch seinen zeitlich veränderlichen Zustand [dynamisch] gekennzeichnet.
➥ Der aktuelle Ausführungszustand eines Programms wird durch den Prozeß beschrieben!
➥ Der Zustand eines Prozesses kann abhängen von
1. Ein- und Ausgabe von Daten,
2. dem Voranschreiten der Berechnung, d.h. dem aktuell ausgeführten Befehl,
3. dem Inhalt von Speicher- und Registerzellen.
Dr. Stefan Bosse •
Seite 5
Grundlagen der Informatik (B)
Prozeßzustände (I)
➤ Ein einziger Mikroprozessor kann zu einem gegebenen Zeitpunkt immer nur einen Maschinenbefehl eines aktuell laufenden Prozesses ausführen.
➤ Sollen mehrere Prozesse auf einem einzelnen Prozessor ausgeführt werden, bedarf es einer
Prozeßverwaltung, die die Ressource Prozessor abwechselnd den Prozessen zur Verfügung
stellt.
➤ Man unterscheidet dann verschiedene Prozeßzustände:
Zustand RECHNEND
Es kann sich nur ein einziger Prozeß im Zustand RECHNEND befinden, d.h. ausgeführt
werden.
Zustand BLOCKIERT
Alle anderen Prozesse befinden sich im blockierten Zustand, d.,h. sind nicht aktiv, und
oder sind zusätzlich im
Zustand RECHENBEREIT
Dieser Zustand signalisiert, daß ein Prozeß die weitere Ausführung benötigt, ist aber
weiterhin nicht aktiv.
➤ Ein nicht rechenbereiter Prozeß benötigt für seine Ausführung das Auftreten eines Ereignisses (blockiert ➽ wartend), z.B. die Eingabe von Daten.
Seite 6
Dr. Stefan Bosse •
Grundlagen der Informatik (B)
Prozeßzustände (II)
(1)
Prozeßstart
➽ Programm wird in den Hauptspeicher von einem Sekundärspeicher geladen.
➽ Prozeß ist initial bereit
(2) Übergang BEREIT ➽ RECHNEND
Ausführung ➽ Erster (oder nächster) Maschinenbefehl des Programms wird vom Prozessor
ausgeführt. Jeder Prozeß P hat seinen eigenen Befehlszähler BZ(P).
Dr. Stefan Bosse •
Seite 7
Grundlagen der Informatik (B)
Prozeßzustände (III)
(3) Übergang RECHNEND ➽ BEREIT
Damit andere Prozesse (Zustand BEREIT) ausgeführt werden können, müssen zwei Randbedingungen im Prozeßsystem erfüllt sein:
1. Aktueller Prozeß geht explizit in den Zustand WARTEND über (auf Ereignis warten), oder
2. der aktuelle Prozeß wird nach einer Zeitspanne τ (z.B. 20 ms) implizit in den Zustand
BEREIT versetzt ➽ ein anderer Prozeß wird ausgeführt!
Seite 8
Dr. Stefan Bosse •
Grundlagen der Informatik (B)
Prozeßzustände (IV)
(4) Übergang RECHNEND ➽ WARTEND
Der Prozeß muß auf ein Ereignis warten:
Eingabe von der Tastatur
Lesen von Daten eines langsamen Speichermediums (CDROM)
Ausgabe von Daten auf Peripheriegeräte (Drucker, z.B. nich empfangsbereit)
Vom Programm explizit veranlasste Verzögerung des Programmablaufs (Verzögerung
um feste Zeitspanne)
Dr. Stefan Bosse •
Seite 9
Grundlagen der Informatik (B)
Prozeßzustände (V)
(5) Übergang WARTEND ➽ BEREIT
Das Ereignis auf das das Programm gewartet hat ist eingetreten. Der Prozeß geht in den
Zustand BEREIT über, und wird baldmöglichst wieder ausgeführt..
(6)
Der Prozeß wird beendet:
1. Das reguläre Programmende wurde erreicht (Terminierungskriterium)
2. Es ist ein Fehler aufgetreten, der nicht abgefangen wurde (DIV 0!)
Seite 10
Dr. Stefan Bosse •
Grundlagen der Informatik (B)
Speichermodell eines Prozesses (I)
➤ Ein Programm wird in den Hauptspeicher geladen, bevor es als Prozeß ausgeführt wird.
Das Programm liegt auf einem Sekundärspeicher binärkodiert (≡ anonyme Folge von Datenwörtern) vor.
➤ Bei Mikro-Controllern wird das Programm i.A. direkt aus dem Langzeitspeicher (ROM) ausgeführt.
➤ Ein Prozeß belegt i.A. nur einen Teil des Hauptspeichers.
➤ Der Speicherbereich eines Prozesses ist in einzelne Teilsegmente unterteilt, die verschiedene Arten von Daten beinhalten.
Dr. Stefan Bosse •
Seite 11
Grundlagen der Informatik (B)
Speichermodell eines Prozesses :: Speichersegmente
➤ Man unterscheidet folgende Speichersegmente eines Prozesses:
Textsegment
Der eigentliche Programmkode, d.h. die Maschinenbefehle des Programms, befinden sich im sog. Textsegment.
Dieses Datensegment wird während der Programmausführung [Größe, Dateninhalt] nicht verändert!
Datensegment
Im Datensegment befinden sich Programmdaten, wie z.B.
Textzeichenketten, Variablen usw.
Man unterscheidet:
A) nicht initialisierte Daten ➽ der Inhalt der Speicherzellen wird erstmalig zur Laufzeit des Programms verändert.
B) initialisierte Daten ➽ der Inhalt der Speicherzellen enthält zum Programmstart vom Programm vorgegebene Werte (z.B. Textzeichenkette
line=”HARWDARE”).
Das Datensegment ist in Größe und Inhalt während der
Prozeßausführung veränderlich!
Seite 12
Dr. Stefan Bosse •
Grundlagen der Informatik (B)
Speichermodell eines Prozesses :: Speichersegmente
Stacksegment
Der Stackspeicher wird von einem Prozeß als temporärer
Datenspeicher (kurzfristig) benötigt.
Bei einem Stackspeicher-Modell ≡ Stapelspeicher
kann immer nur die aktuellste (≡ oberste) Speicherzelle (des Stacks) gelesen und beschrieben werden.
Es wird ein Speicherzeiger P auf eine Speicherzelle
vom Speicher S benötigt.
Modell: LastIn - FirstOut (LIFO)
Operationen:
PUSH(x)
S(P)←x; P←P+1;
Wert x im Stack speichern.
POP(X)
P←P-1; x←S(P);
Wert aus Stack lesen und in x übertragen.
Der Stack-Speicher muß durch Soft- oder Hardware
implementiert werden, da der lineare Hauptspeicher
dieses Zugriffsmodell nicht unterstützt!
Dr. Stefan Bosse •
Seite 13
Grundlagen der Informatik (B)
Prozeßverwaltung :: Foreground-Background-System
➤ Minimale Anforderungen an ein Datenverarbeitungssystem:
1. Die Datenverarbeitung findet programmgesteuert statt, d.h. es gibt ein Programm.
2. Bei rein funktionalen Systemen, wo eine eindeutige Abbildung der Eingangsdaten auf
Ausgangsdaten möglich ist (theoretisch in einem einzigen Zeitschritt), reicht die alleinige
Ausführung des funktionalen Programms aus.
3. Bei einem reaktiven System, wo die Eingangsdaten ereignisbasiert verarbeitet
werden, z.B. Texteditor, Getränkeautomat usw., wird neben der eigentlichen Programmausführung die Bearbeitung der Ereignisse und Aufnahme der Eingabedaten benötigt.
➽ Verarbeitung der Ereignisse und Datenverarbeitungsprogramm müssen i.A. unterschiedl
che Prioritäten besitzen. Ereignisse (≡ Ein-und Ausgabedaten) müssen daher mit höherer Prioritä
abgearbeitet werden!
➤ Einfachstes Prozeß-Systemmodell
Hauptprozeß
➽ Es gibt nur einen einzigen primären Prozeß.
➽ Dieser Prozeß wird als Hintergrundprozeß mit niedrigster Priorität ausgeführt.
➽ Eine Prozeßverwaltung ist nicht notwendig!
Nebenprozeß
➽ ”Prozeß” mit höchster Priorität, der die Bearbeitung des Hauptprozesses beim Eintreten von Ereignissen unterbricht.
➽ Interrupt-Handler
Seite 14
Dr. Stefan Bosse •
Grundlagen der Informatik (B)
Prozeßverwaltung :: Foreground-Background-System (II)
Dr. Stefan Bosse •
Seite 15
Grundlagen der Informatik (B)
Prozeßverwaltung :: Der Scheduler (I)
➤ Der Scheduler (≡ Ablaufplaner) ist für die Prozeßverwaltung im Betriebssystem mit Multitasking (≡ Mehrprozeßbetrieb) zuständig.
➤ Der Scheduler teilt Prozessen die Prozessorlaufzeit zu und führt die Prozeßumschaltung
durch.
➤ Bei der Prozeßumschaltung wird der aktuell laufende Prozeß P i angehalten, und ein neuer
bereiter Prozeß Pj zur Ausführun vorbereitet (task switch).
➤ Alle Prozesse eines Rechners werden in der Prozeßtabelle verwaltet:
Prozeßverwaltung
Speicherverwaltung
Nutzerverwaltung
Prozessorregister
Speicheradressen
Nutzer ID #
Programmzähler BZ
➽ Segmente
Gruppen ID #
Prozeßstatus
• Textsegment
Arbeitsverzeichnis
Stackzeiger SZ
• Datensegment(e)
Zugriffs-Rechte
Prozeß ID #
• Stacksegment(e)
Ausführungs-Rechte
Statistiken
Priorität
Seite 16
Dr. Stefan Bosse •
Grundlagen der Informatik (B)
Prozeßverwaltung :: Der Scheduler (II)
Dr. Stefan Bosse •
Seite 17
Grundlagen der Informatik (B)
Prozeßverwaltung :: Der Scheduler (III)
➤ Die Reihenfolge, in der einzelne Prozesse ausgeführt werden, kann durch verschiedene Zuteilungsstrategien erfolgen:
1. nach Eingangsreihenfolge (FirstCome - FirstServed FCFS)
2. nach Zeitscheibenverfahren (Round-Robin)
3. nach Prioritäten
➤ Weiterhin unterscheidet man das Verhalten beim Eintreten von Ereignissen (nicht InterruptHandler!):
Preemptives Schalten
Beim Eintritt eines Ereignisses können sich die Zustände von Prozessen ändern. Ein
Prozeß kann vom Zustand WARTEND in den Zustand BEREIT übergehen. Bei dieser
Scheduling-Methode wird der aktuell laufende Prozeß unter bestimmten Randbedingungen angehalten, und die Ausführung an den gerade bereit gewordenen Prozeß übergeben.
Nicht-Preemptives Schalten
Auch hier können Ereignisse die Zustände von wartenden Prozessen verändern. Aber
der aktuell laufende Prozeß wird unter keinen Umständen angehalten, sofern dieser
Prozeß nicht explizit die Ausführung unterbricht (auf Ereignis warten, z.B. bei VTURI
der READ Befehl!).
Seite 18
Dr. Stefan Bosse •
Grundlagen der Informatik (B)
Prozeßverwaltung :: Der Scheduler (IV)
Scheduling Methode Eingangsreihenfolge (FCFS)
➤ Prozesse werden der CPU in der Reihenfolge zugewiesen wie sie Rechenbedarf anmelden.
➤ Ein laufender Prozeß wird nicht zwangsläufig unterbochen.
➤ Rechenbedarf wird durch den Zustandsübergang
WARTEND ➽ BEREIT
signalisiert.
➤ Nachteil: Kurz laufende Prozesse, die EA-Ereignisse verarbeiten, werden von lange laufenden Prozessen stark verzögert.
➽ Antwortzeit des Systems ist subjektiv unbefriedigend!
Seite 19
Dr. Stefan Bosse •
Grundlagen der Informatik (B)
Prozeßverwaltung :: Der Scheduler (V)
Scheduling Methode Zeitscheibenverfahren (Round-Robin)
➤ Alle Prozesse werden reihum bearbeitet.
➤ Ein aktuell laufender Prozeß wird eine Zeitspanne τ zugewiesen, die er nicht überschreiten
darf. Eine vorzeitige Abgabe der Ausfüjhrung vom Programm aus ist möglich.
➤ Erreicht ein Prozeß das Zeitpensum τ, wird er angehalten, und der nächste Prozeß im Zustand BEREIT wird ausgeführt, bis auch diese seine Zeitspanne ausgeschöpft hat.
➤ Nachteil: häufige Prozeßwechsel (Scheduler ≡ Maschinenbefehle ≡ Programmcode!) bedeuten Overhead.
Seite 20
Dr. Stefan Bosse •
Grundlagen der Informatik (B)
Prozeßverwaltung :: Der Scheduler (VI)
Prioritätenbasierte Scheduling Methode
➤ Prozesse besitzen eine Priorität, so daß sich der Zustand eines Prozesses aus dem eigentlichen Aktivitätszustand {RECHNEND,BEREIT,WARTEND} und der Priorität, i.A. eine
Integerzahl, zusammensetzt.
➤ Prioritäten können statisch (zeitlich unveränderlich) oder dynamisch (zeitlich veränderlich)
sein.
➤ Ein aktuell laufernder Prozeß kann unterbrochen werden, wenn ein anderer Prozeß mit höherer Priorität rechenbereit wird (aufgrund eines Ereignisses).
➤ Die Priorität eines Prozesses kann mit fortlaufender Rechenzeit verringert werden, und
durch Eintreten eines Ereignisses wieder erhöht werden.
Dr. Stefan Bosse •
Seite 21
Grundlagen der Informatik (B)
Dateien und Dateisysteme (I)
➤ Eine Datei ist eine Sammlung von Daten, die auf einem Langzeitspeicher gehalten wird.
➤ Datenmodell: Die einzelnen Daten werden sequenziell angeordnet ➽ lineare Folge von
Daten.
➤ Das Lesen und Schreiben einer Datei erfolgt daher ebenfalls sequenziell mit einem Dateizeiger.
➤ Nach jeder Lese- oder Schreiboperation wir der Dateizeiger entsprechend der gelesenenoder geschriebenen Datenmenge weitergesetzt,
Dateianfang
T
Dateizeiger
E
X
T
[064]
Logische
Position
in
der Datei
Dateiende
Dateizelle mit fester Bitbreite
Seite 22
Dr. Stefan Bosse •
Grundlagen der Informatik (B)
Dateien und Dateisysteme (II)
➤ In einer Datei können beliebig kodierte Daten gespeichert werden, z.B. Zeichenketten, Fließkommazahlen, oder eine Aggregation (Datenstruktur) aus verschiedenen Datentypen und
Datenobjekten.
➤ Ein Dateisystem, welches Bestandteil des Betriebssystems ist, stellt einen Abstraktionsmechanismus dar, um Daten bzw. Dateien auf dem Speichermedium zugänglich zu machen,
ohne daß der Benutzer sich mit Einzelheiten der Datenspeicherung befassen muß.
➤ Ein Dateisystem bietet zusätzlich:
Zugriffsrechte
Verwaltung und Überwachung von Zugriffsrechten auf Dateien in einem Dateisystem
➽
{Schreiboperation, Leseoperation,
Löschoperation, Ausführung von Programmen}
Dateinformationen
{Dateigröße, Dateiart, Zugriffsrechte, Eigentümer}
Dateistrukturierung
Hierarchische Anordnung von Dateien in Suchbäumen mit Suchpfaden.
Dr. Stefan Bosse •
Seite 23
Grundlagen der Informatik (B)
Logische Struktur von Dateisystemen (I)
➤ Um eine Zugrifssmöglichkeit auf Dateien zu haben, werden verschiedene Dateien mittels
eines Inhaltsverzeichnisses strukturiert ➽ Verzeichnisse (Directories) ➽ Dateien werden
einem Verzeichnis zugeordnet.
➤ Ein Verzeichnis wird ebenfalls mit einem Namen bezeichnet.
➤ Eine Vielzahl von Verzeichnissen werden hierrachisch mit einer Baumstruktur verknüpft ➽
Verzeichnisbaum.
V1
V2
V5
V3
V6
Verzeichnis
V4
[065]
Datei
➤ In einem Verzeichnisbaum wird eine Datei nicht mehr allein durch ihren Namen bezeichnet,
sondern zusätzlich durch ihren Pfadnamen.
Seite 24
Dr. Stefan Bosse •
Grundlagen der Informatik (B)
Logische Struktur von Dateisystemen (II)
➤ Beispiel:
top
files
mydat
docs
mydat
[066]
➤ Zwei Dateien mit gleichen Namen werden durch unterschiedliche Pfade unterschieden:
Datei 1 ⇒ top/files/mydat
Datei 2 ⇒ top/docs/mydat
➤ Jede Datei und jedes Verzeichnis besitzen ein Elternverzeichnis. Bei Verzeichnissen ist es
das Vorgängerverzeichnis.
➤ Der Wurzelknoten, das Wurzelverzeichnis, wird i.A. mit dem Namen ’/’ anstelle eines Textnamens bezeichnet. Das Wurzelverzeichnis besitzt keinen Vorgänger!
Seite 25
Dr. Stefan Bosse •
Grundlagen der Informatik (B)
Physische Struktur von Dateisystemen (I)
➤ Die Abbildung der linearen logischen Struktur (abstrahiertes Modell) einer Datei auf die
technischen Einzelheiten eines Spreichermediums bezeichnet man als physische Struktur(ierung).
➤ Die Abbildung auf technische Einzelheiten findet durch das Betriebssystem in mehreren Stufen statt, die schrittweise den Abstraktionsgrad verkleinern:
1. Verzeichnisstruktur als übergeordneter Suchbaum (Orgranisation),
2. Ebene III: Darstellung der Datei als lineare logische Dateistruktur,
3. Blockstrukturierung, Fragmentierung, Abbildung der Datei auf forlaufend numerierte Datenblöcke fester Länge im Kontext des Dateisystems,
4. Ebene II: Dateisystem (1..3)
5. Ebene I: Gerätetreiber, Abbildung der Datenblöcke auf technisches Speichermedium
und Geometrie des Speichermediums.
➤ Ein Festplatten- oder CDROM-Speiher ist in zylindrische Spuren unterteilt. Jede Spur ist in
Sektoren bestimmter Größe weiter unterteilt.
➤ Zur Vereinfachung der Speicherung der Dateidaten besitzt jede Spur die gleiche Anzahl von
Sektoren.
Aber: auf technischer Ebene 0 besitzt jede Spur unterschiedliche Anzahl von Sektoren bzw.
Anzahl von Datenbits!
➤ Abbildung der homogenenen zylindrischen Speichergeometrie auf technisch realisierbare
inhomogene Geometrie ist Aufgabe des Speichergerätes!
Seite 26
Dr. Stefan Bosse •
Grundlagen der Informatik (B)
Physische Struktur von Dateisystemen (II)
Dateisystem => logische
Block-Struktur
Datei => logische Struktur
POS 0
write
Dateioffset
read
BLOCK
100
Speichermedium =>
physische Struktur
Sektor 7
Sektor 0
Spur 0,1,2
Sektor 1
Blockoffset
seek
POS 1792
[067]
BLOCK
103
➤ Die einzelnen Blöcke einer Datei werden einzelnen Sektoren der Festplatte nach zwei verschiedenen Methoden zugeordnet:
1. möglichst geschlossen/zusammenhängend sequenziell auf Spuren,
2. oder verstreut auf verschiedenen Sektoren von verschiedenen Spuren (nicht zusammenhängend).
Block
100
101
102
103
Spur (1)
1
1
1
1
Sektor (1)
3
4
5
6
Spur (2)
2
27
10
2
Sektor (2)
0
3
4
2
Dr. Stefan Bosse •
Seite 27
Grundlagen der Informatik (B)
Minix-Dateisystem :: Allgemeiner Aufbau
➤ Die Strukturierung des Dateisystems ist unterteilt in
folgende Funktionsblöcke:
Super Block
Dieser Block enthält Informationen über das Dateisystem:
1.
2.
3.
4.
Anzahl der Inodes
Anzahl der Datenblöcke
Blockgröße [Bytes]
usw.
Inode Table
Inodes enthalten Informationen über Dateiobjekte:
1.
2.
3.
4.
Dateiart
Größe
Zeitstempel
Zeiger auf Datenblöcke
Data
Datenbereich
Seite 28
Dr. Stefan Bosse •
Grundlagen der Informatik (B)
Minix-Dateisystem :: I-Node
➤ Eine I-Node ist eine interne Verknüpfung. Sie enthält Informationen über eine Datei, aber
nicht den Namen der Datei (oder eines Verzeichnisses). Dieser wird im Datenbereich abgelegt.
➽ Inode-Format (mit Byteoffset)
0
2
MODE UID
P1
P2
4
SIZE
P3
P4
8
TIME
P5
P6
12 13 14
G L P0
P7
P8
Mode
Art des Dateninhaltes/der Inode:
{FREG ➽ Regular File, FDIR: Directory, FLNK: Link, ...}
SIZE
Größe der Datei in Bytes (oder in Blockeinheiten)
UID, GID, TIME
Nutzer-ID & Gruppen-ID & Zeitstempel
P0...P6
Zeiger auf Datenblöcke
P7, P8
Zeiger auf Zeigerblock, der weitere Datenblockzeiger P enthält, und doppelt indirekter Zeiger.
Seite 29
Dr. Stefan Bosse •
Grundlagen der Informatik (B)
Minix-Dateisystem :: Beispiel einer Datei und einer I-Node
Seite 30
Dr. Stefan Bosse •
Grundlagen der Informatik (B)
Minix-Dateisystem :: Verzeichnis
➤ Verzeichnisse werden im Minix-Dateisystem wie normale Dateien behandelt.
➤ Ein Verzeichnis ist ein Datenblock mit einer linearen Liste von Verzeichniseinträgen.
Datenblock
Verzeichniseintrag 1
→
Datei 1
Verzeichniseintrag 2
→
Datei 2
→
Datei N
••••
Verzeichniseintrag N
➤ Ein Verzeichniseintrag enthält den Namen des Eintrages und ein zugehörge I-Node-Nummer,
die entweder zu einer Datei oder einem weiteren Verzeichnis gehört (Verzeichnisbaum).
Verzeichniseintrag
2
Link
Seite 31
Inode
14
Name
Dr. Stefan Bosse •
Grundlagen der Informatik (B)
Minix-Dateisystem :: Beispiel einer Datei und Verzeichnisse (I)
Seite 32
Dr. Stefan Bosse •
Grundlagen der Informatik (B)
Minix-Dateisystem :: Beispiel einer Datei und Verzeichnisse (II)
Dr. Stefan Bosse •
Seite 33
Grundlagen der Informatik (B)
Minix-Dateisystem :: Große Dateien
➤ I.A. ist die Blockgröße BLKSIZE=512 Byte.
➤ Die Blockgröße entscheidet über:
1. die maximal Anzahl von zu speichernden Blöcken,
2. die Verschwendung an Speicherplatz, da Dateien und Verzeichnisse nur in Vielfachen
von Blöcken gespeichert werden können.
➤ Neben den eigentlichen Dateidaten und Inodes müssen in der Inode-Map und Data-Map
➤
➤
➤
➤
Seite 34
Tabelle die bereits verwendeten Blöcke, jeweils für den Inode- und Data-Bereich vermerkt
werden.
Die Anzahl von Inodes ist durch die Größe der Inode-Tabelle und der Inode-Map-Tabelle
beschränkt.
Die Anzahl der Datenblöcke ist durch die Data-Map-Tabelle beschränkt.
Damit auch größere Dateien gespeichert werden können (N Blcke>7=3584 Bytes), kann ein
weiterer Datenblock als Zeigerblock verwendet werden [P7], so daß weitere M=BLKSIZE/2
Datenblockzeiger zur Verfügung stehen ➽ indirekter Blockzeiger.
Weitere Zeigerblöcke sind über einen doppelt indirekten Blockzeiger P8 erreichbar. Dieser
Block enthält Zeiger auf Zeigerblöcke, die wiederum Zeiger auf Datenblöcke enthalten.
Dr. Stefan Bosse •
Grundlagen der Informatik (B)
Programme und Programmiersprachen (I)
➤ Programme beschreiben im einfachsten Fall die Umsetzung von Algorithmen.
➤ Diese Algorithmen beschreiben eine Abbildung f: E →A von Eingabedaten E nach Ausgabedaten A.
➤ Diese Beschreibung soll
1. für den menschlichen Leser und
2. maschinell verständlich sein.
➤ Die Eingaben E und die Ausgaben A sind Daten, die durch Folgen von Bits kodiert werden.
➤ Ein Algorithmus beschreibt ein Verfahren zur Lösung eines Problems:
Dr. Stefan Bosse •
Seite 35
Grundlagen der Informatik (B)
Programme und Programmiersprachen (II)
➤ Programmieren, d.h. die Erstellung eines Programms, unterteilt sich in drei Teilschritte:
Spezifikation
Genaue Beschreibung des zu lösenden Problems und der Ein- und Ausgabedaten (Format, Kodierung, Datenmenge usw.)
Algorithmus
Erarbeitung eines (schrittweisen) Lösungsweges und Verfahrens.
Programm
Umsetzung des Algorithmus mit einer konkreten Programmiersprache mit dem Ziel,
Anweisungen für eine Maschine zu erzeugen (lineare Liste von Maschinenbefehlen).
Die Programmiersprache soll möglichst von technischen Einzelheiten der Maschine
und eines eventuell vorhandenen Betriebssystems abstrahieren.
Beim Abstraktionsgrad wird unterschieden
Low-level
Maschinenahe Sprache, die nur minimal die Maschine abstrahiert ➽ Programme
(Quellkode) nicht portabel zwischen verschiedenen Maschinen ➽ das Programm
ist wenig strukturiert.
High-level
Hochsprache, die maximal die Maschine abstrahiert ➽ Programme sind portabel
zwischen verschiedenen Maschinen ➽ das Programm ist strukturiert.
Seite 36
Dr. Stefan Bosse •
Grundlagen der Informatik (B)
Programme und Programmiersprachen :: Algorithmus
➤ Ein Algorithmus ist definiert durch:
1.
2.
3.
4.
Die Ausführung des Algorithmus erfolgt in einzelnen Schritten.
Jeder Schritt besteht aus einer einfachen Grundaktion.
Zu jedem Zeitpunkt ist eindeutig bestimmt, welcher Schritt als nächster auszuführen ist.
Ein Algoritmus muß nach endlicher Zahl von Schritten terminieren. Nur bei funktionalen
Systemen nachweisbar erfüllbar.
➤ Ein Algorithmus kann von einem Menschen und von einer Maschine ausgeführt werden.
➤ Ein Programm wird hingegen nur von einer Maschine ausgeführt.
➤ Algorithmen lassen sich darstellen durch:
◆ Grafische Darstellung durch Flußdiagramme und Flußgraphen, eventuell in Daten- und
Kontrollpfade zerlegt.
◆ Funktionsdiagramme und Bäume
◆ Abstrakte Programmiersprache mit Pseudo-Notation, die die wesentlichen Ablaufschritte verdeutlicht, aber nicht detaliert ist.
◆ Konkrete Programmiersprachen.
➤ Elementare Aktionen in einem Algorithmus:
1. Datenpfad ➽ Datenabhängigkeiten und Verarbeitung mit Funktionseinheiten
2. Kontrollpfad ➽ Ablaufsteuerung
Seite 37
Dr. Stefan Bosse •
Grundlagen der Informatik (B)
Programme und Programmiersprachen :: Flußdiagramm
➤ Elementare Bestandteile eines Flußdiagramms:
Seite 38
Dr. Stefan Bosse •
Grundlagen der Informatik (B)
Flußdiagramm :: Beispiel (I)
Spezifikation
Es soll der größte gemeinsame Teiler T zweier Zahlen N und M bestimmt werden.
N und M sind ganze Zahlen. Das Ergebnis ist ebenfalls eine ganze Zahl. Es muß der Fall
N=0 oder M=0 ausgschlossen werden.
Algorithmus
Dr. Stefan Bosse •
Seite 39
Grundlagen der Informatik (B)
Flußdiagramm :: Beispiel (II)
Programmierung (Imperative Programmiersprache C)
int ggt(int N, int M) Funktion mit Operanden
{
int x=n; int y=M; Variablen
while (x!=y) Schleife
{
if (x>y) x=x−y; Bedingte Verzweigung
else
y=y−x;
};
return x; Rückgabe Ergebnis T
}
Verwendung von Variablen mit Rückwirkung, d.h. der Wert einer Variablen wird im Kontrollfluß vor der Zuweisung gelesen (Schleife!).
Explizite Spezifikation des Kontrollflusses erforderlich.
Beweis der Terminierung aufwendig und kompliziert.
Seite 40
Dr. Stefan Bosse •
Grundlagen der Informatik (B)
Flußdiagramm :: Beispiel (III)
Programmierung (Funktionale Programmiersprache ML)
let rec ggt = fun x y →
Funktion
if x<y then ggt (x−y) y
Bedingte Verzweigung
else if x>y then ggt x (y−x)
else x Rückgabe Ergebnis T
Keine Variablen mir Seiteneffekten, d.h. Lesen eines Datenkontainers im Kontrollfluß
bevor die Wertzuweisung erfolgt (keine Schleifen!).
Ausnutzung von Rekursion und bedingte Verzweigung.
Eigentlicher Kontrollfluß wird nicht explizit spezifiziert!
Stattdessen wird der funktionale Zusammenhang ähnlich einer mathematischen Formel
spezifiziert.
Beweis der Terminierung einfacher als bei imperativen Programmen.
Dr. Stefan Bosse •
Seite 41
Grundlagen der Informatik (B)
Reaktive und funktionale Systeme (I)
Funktionale Systeme
Funktionale Systeme sind gekennzeichnet durch einen eindeutigen Zusammenhang zwischen den Eingabedaten E und der Ausgabedaten A durch eine Abbildung f:E→A.
Ein funktionales System kann prinizipiell in einem einzigen Zeitschritt ausgeführt werden, analog einer mathematischen Funktion, die keinen Kontrollfluß spezifiziert, sondern nur einen Datenfluß. Die Menge der Eingabedaten liegt zu Programmbeginn bereits fest.
Die Menge der Ausgabedaten und deren Werte hängen nur von der Menge der Eingabedaten ab.
Die Menge der Ausgabedaten hängt nicht vom Programmablauf und dem zeitlich veränderlichen Zustand des Programms ab.
Reaktive Systeme
Neben funktionalen Systemen gibt es reaktive Systeme bzw. Programme. Bei denen stehen
die Eingabedaten E nicht zu Beginn einer ”Berechnung” fest.
Bei einem reaktiven System wird ein Strom von Eingabedaten, die nur schrittweise bekannt werden, zu einem Strom von Ausgabedaten verarbeitet (ebenfalls schrittweise).
Die Ausgabedaten hängen neben den Eingabedaten vom zeitlich veränderlichen Zustand des Systems bzw. Programms ab!
Reaktive = interaktive Systeme bzw. Programme müssen nicht das Terminierungskriterium eines Algorithmus erfüllen!
Seite 42
Dr. Stefan Bosse •
Grundlagen der Informatik (B)
Reaktive und funktionale Systeme (II)
Beispiele für funktionale und reaktive Systeme
Funktionales System
T=ggt(N,M)
➥ E={N,M}
➥ A={T}
➥ f: E→A
Reaktives System
Texteditor
➥ E={Textzeichen}
➥ A={Textdatei}
➥ interaktives Programm
➥ bereits eingegebene Daten
können verändert oder gelöscht
werden, d.h. A ist abhängig vom
aktuellen Programmzustand ℘(n)
und vergangenen Zuständen
℘(n-1)· · ·℘(0)
f(℘): E → A(℘)
Dr. Stefan Bosse •
Seite 43
Grundlagen der Informatik (B)
Programmerstellung (I)
Arbeitsablauf bei der Programmerstellung
Zyklus: Edit-Compile-Run
1. Mit Hilfe eines Editors wird ein Programmtext geschrieben (Quellcode).
2. Dieser Text wird mit einem Übersetzer (Compiler) in ein Maschinenprogramm synthetisiert/tranformiert (compiliert):
Analyse
Zuerst wird der Programmtext analysiert und auf Fehler überprüft.
➥ Bei Fehlern wieder 1.) und Korrektur (Rückkopplung im Entwurfsprozeß)
Synthese
Nach erfolgreicher Analyse wird Maschinencode erzeugt.
3. Das Maschinenprogramm kann ausgeführt werden, und bekommt vom Rechner und
Betriebssystem Eingabedaten zur Laufzeit, und generiert Ausgabedaten.
➥ Überprüfung der Funktion des Programms. Bei Fehler wieder 1.) und 2.) und Korrektur.
➤ Der obige Zyklus Edit-Compile-Run ist im Allgemeinen recht (zeit-) aufwendig und unhandlich bezüglich Fehleranalyse und Korrektur (getrennte Programme). Bei einem Interpreter
befindet sich der Compiler und das Ausführungssystem in einem Programm
➤ Die Erzeugung von Maschinencode entfällt teilweise bis gänzlich. Häufig wird eine virtuelle
Maschine im Interpreter zur Ausführung des zu bearbeitenden Programms verwendet.
Seite 44
Dr. Stefan Bosse •
Grundlagen der Informatik (B)
Programmerstellung (II)
Dr. Stefan Bosse •
Seite 45
Grundlagen der Informatik (B)
Programmiersprachen (I)
Def.
Eine Programmiersprache ist eine Notation für Programme, also für Beschreibungen von
Berechnungen.
➤ Diese Notation soll
1. für den menschlichen Leser verständlich,
2. effizient auf einer Maschine implementierbar sein, und
3. ein Hilfsmittel zur Strukturierung, Modularisierung und Partitionierung eines großen Gesamtproblems in kleinere Einheiten bieten.
➤ Man unterscheidet maschinennahe und höhere Sprachen, die sich mehr am menschlichen
Verständins orientieren.
➤ Maschinennahe Sprachen entsprechen umkehrbar eindeutig der Befehlskodierung der Maschine, die sog. Assembler-Sprachen, z.B. VTURI:
LOAD 0;
STORE R[0];
STORE R[1];
L: READ;
Seite 46
⇔
⇔
⇔
⇔
1010000100000000
1011001000000000
1011001000000001
1000000000000000
Dr. Stefan Bosse •
Grundlagen der Informatik (B)
Programmiersprachen (II)
➤ Vor- und Nachteile:
⊕ Sprache und Übersetzer sind leicht zu implementieren.
Programmierung mit diesen Sprachen ist aufwendig und fehleranfällig ➽ siehe VTURI!
Direkte Abhängigkeit von der Rechnerarchitektur, Programme sind nicht portabel, d.h.
für jede Rechnerarchitektur muß ein vollständig neues Programm entwickelt werden.
Keine Möglichkeit der Strukturierung und Modularisierung (Kapselung).
Datenkodierung muß vom Programmierer erfolgen, keine Unterstützung durch Typen.
➤ Höhere Programmiersprachen sind Abstraktionen von maschinennaher Programmierung
und der Rechnerarchitektur.
➤ Vorteile:
⊕ Implementierung eines Algorithmus und Beschreibung der Berechnung mit komplexen
Befehlskonstrukten und Datenstrukturierung, dadurch Reduktion von Programmierfehlern.
⊕ Unterstützung durch Datentypen und Typüberprüfung zur Erkennung von fehlerhaften
Ausdrücken und Anweisungen.
⊕ Programmstrukturierung durch Funktionen, Module und Objekte, portable Programme.
Seite 47
Dr. Stefan Bosse •
Grundlagen der Informatik (B)
Dr. Stefan Bosse •
Grundlagen der Informatik (B)
Programmiersprachen (III)
➤ Nachteile:
Fehlender Bezug zur Rechnerarchitektur reduziert Möglichkeiten der Optimierung (Laufzeit und Speicherbedarf), nur durch den
Übersetzer möglich.
Fehler im Übersetzer (!) schwer aufzudecken.
➤ Höhere Programmiersprachen lassen sich durch
das zugrunde liegende Berechnungsmodell
klassifizieren:
Imperative Programmiersprachen
Speichermodell ➽ {C, Pascal, Modula}
Funktionale Programmiersprachen
Funktionsmodell ➽ {ML, Haskell, LISP,
OCAML, SML}
Logische Programmiersprachen
Aussagenlogik ➽ {Prolog}
Hardwarebeschreibungssprachen
Verhaltens- und Strukturbeschreibung von
Hardware ➽ {VHDL, Verilog}
Seite 48
Programmiersprachen :: Die Anfänge: Programmierer als Drahtstöpsler
ENIACComputer,
ca. 1947
Seite 49
Dr. Stefan Bosse •
Grundlagen der Informatik (B)
Dr. Stefan Bosse •
Grundlagen der Informatik (B)
Programmiersprachen :: Übersicht
Seite 50
Programmiersprachen :: Imperativ
➤ Imperative Sprachen beschreiben eine Berechnung als Folge von Zustandsänderungen
und einzelnen Anweisungen. Es wird eine sequenzielle Ablaufsteuerung explizit beschrieben.
Zustandsänderung ⇔Speicheränderung
➤ Variablenkonzept: benannte Datenkontainer, die in beliebiger Reihenfolge gelesen und denen
Werte zugewiesen werden können (inklusive Rückwirkung).
➤ Alle maschinenahen Sprachen für v. Neumann-Rechner sind imperativ.
➤ Ein imperatives Programm besteht aus einer Vielzahl teils komplexer Anweisungen und Befehle:
1. Zuweisungen von Werten an Variablen, Lesen von Werten aus Variablen, Verknüpfungen von Werten zu neuen Werten mit arithmetischen und logischen Operatoren.
Beispiel C: x=x+5;
➥ wesentliche Zustandänderung
2. Ablaufsteuerung:
A) Bedingte Verzweigungen
B) Schleifen
Beispiel C: Schleife
C) Funktionen
while (x != y)
D) Fallunterscheidungen (Mustersuche)
{ x=x+1;};
Dr. Stefan Bosse •
Seite 51
Grundlagen der Informatik (B)
Programmiersprachen :: Imperativ :: Charakteristica [PEP02]
➤ Ein Programm ist eine Arbeitsweisung für eine Maschine.
➤ Als Nebenprodukt ihrer Arbeit liefert diese Maschine zu den gegebenen Eingabedaten die
zugehörigen Ausgabedaten.
➤ Das Ein-/Ausgabeverhalten läßt sich anhand der Arbeitsweise der Maschine analysieren.
➤ Daher werden Programme sehr konkret auf Maschinen bezogen, die Maschine ist zentraler
Bestandteil des Programmiermodells.
➤ Was ein Programmstück tut, hängt vom Zustand ab, in dem sich die Maschine gerade befindet. Dieser Zustand ändert sich mit der Zeit, z.B. die Zählvariable einer Schleife.
➤ Um ein Programm zu verstehen, muß man immer seinen zeitlichen Ablauf betrachten!
Beispiele
ALGOL
ALGOrithmic Language
C
B ➽ C?
Seite 52
Hochsprache, ab 1958, für wissenschaftliche und
numerische Zwecke: Prozeduren, Blöcke, höhere
Kontrollstrukturen, dynamische Arrays,
benutzerdefinierte Typen, reservierte
Schlüsselwörter, Syntax formal definiert
Problemorientierte Programmiersprache, ab
1974, aber maschinennah (ähnlich
Assemblersprache). Entwicklung verknüpft mit
der Entwicklung des Betriebssystems Unix.
Dr. Stefan Bosse •
Grundlagen der Informatik (B)
Programmiersprachen :: Imperativ :: Charakteristica (II)
Beispiele (fortz.)
FORTRAN
FORmula TRANslator
Hochsprache, ab 1954, für numerische
Zwecke:Ursprache aller algorithmisch
orientierten wissenschaftlichen
Programmiersprachen, Programmcode war
klar strukturiert, Formeln konnten in nahezu
mathematischer Syntax eingegeben werden,
der Programmierer mußte sich nicht mehr um
die explizite Speicherverwaltung kümmern,
im Vergleich zu Assemblerpogrammierung.
PASCAL
französicher Hochsprache, ab 1982, für Lehrzwecke,
Mathematiker und
• Strukturierte Programmierung: Zusammenfassung von
Philosoph,
Anweisungen in Prozeduren und Funktionen bzw. von
Blaise
Datengruppen in komplexe Datentypen. Lesbarkeit und
Pascal
Fehlerkorrektur werden erleichtert.
(16231662)
• Top Down Entwurf: Der Programmierer zerlegt seine Aufgabe in
Teilprobleme, ohne sich zunächst um die Realisierung auf den
unteren Ebenen zu kümmern
• objektorientierte Programmierung
Dr. Stefan Bosse •
Seite 53
Grundlagen der Informatik (B)
Programmiersprachen :: Funktional :: Charakteristika [PEP02]
➤ Ein Programm ist eine Ein-/Ausgaberelation, d.h. eine Abbildung von Eingabedaten auf zugehörige Ausgabedaten.
➤ Diese Abbildung wird im Programmtext direkt als Funktion hingeschrieben.
➤ Programme sind ”zeitlos”. Eine Funktion liefert zu jedem Zeitpunkt die gleichen Ergebnisse,
wie z.B. die mathematischen Sinusfunktion.
➤ Die Formulierung von Programmen findet auf einem recht abstrakten, mathematisch orientierten Niveau statt.
Beispiele
LISP
LISt Processing
language
OCAML
Objective Categorical
Abstract Machine
Language, INRIA
Seite 54
Hochsprache, ab 1959, für wissenschaftliche
Zwecke: LISP ist eine der am weitesten
verbreiteten symbolverarbeitenden
Programmiersprachen in den Bereichen
Künstliche Intelligenz und Computerlinguistik.
Die Syntax von Lisp ist im Gegensatz zu der
anderer Programmiersprachen sehr einfach.
Einzige funktionale Programmiersprache mit:
funktionalen Kern ⊕ imperativen Anweisungen ⊕
objektorientiertes Programmieren ➽ universelle
Programmiersprache, maschinenunabhängig!
Dr. Stefan Bosse •
Grundlagen der Informatik (B)
Programmiersprachen :: Funktionen (I)
Funktionen sind Bestandteil des Programmiermodells einer Vielzahl von Programmiersprachen,
sowohl imperative als auch funktionale!
DEF. Funktion
Eine Funktion f ist eine Tripel hDf ,Wf ,Rf i bestehend aus:
Definitionsmenge Df
Menge aller Funktionsargumente.
Wertemenge Wf
Menge aller Resultatwerte.
Relation Rf
Die Realtion Rf ⊆ Df × Wf gibt die Abbildung der Funktionsargumente (Eingabe) gegeben durch Df =ha1 ,a2 ,..i in Ergebniswerte Wf =hb1 ,b2 ,..i an, auch Funktionsgraph
genannt.
➽ Bei funktionalen Sprachen und Systemen muß dieser Funktionsgraph linkseindeutig
sein, d.h. es gibt keine zwei Parre ha,b1 i und ha,b2 i mit b1 ,b2 .
Beispiele
1. Funktion Quadrat f: x → y mit y=x2 für natürliche Zahlen der Menge ℵ ist gegeben
durch hℵ,ℵ,Ri mit R={h0,0i,h1,1i,h2,4i,h3,9i,...}.
2. Funktion Addition f: u × v → y mit y=u+v für natürliche Zahlen der Menge ℵ ist gegeben
durch hℵ×ℵ,ℵ,Ri mit R={hh0,0i,0i,hh0,1i,1i,...,hh3,2i,5i,...}.
Dr. Stefan Bosse •
Seite 55
Grundlagen der Informatik (B)
Programmiersprachen :: Funktionen (II)
Totale und partielle Funktionen
Es gibt Funktionen, die nicht für alle Werte definiert sind, wie z.B. bei der Division durch Null,
die kein Ergebnis hat. Diese funktionen nennt man partiell. Ist die Funktion für alle Werte
definiert, spricht man von einer totalen Funktion, z.B. Addition.
Totalisierung
Partielle Funktionen sind nicht nur in der Mathematik unbeliebt, auch in der Datenverarbeitung. Deshalb werden Tricks angewendet, um partielle Funktionen zu totalisieren.
Beispiel Division
Bei der binären Fließkommadarstellung wird eine nicht gültige reelle Zahl speziell kodiert,
symbolisch durch NaN (Not a Number) gekennzeichnet, als Binärkode z.B. durch ein spezielles Bit gekennzeichent, oder ein außerhalb des gültigen Bereiches liegender Exponentwert.
Dieser spezielle Wert kann aber im Programm weiter verarbeitet werden, und z.B. abgefragt werden, um eine ungültige arithmetische Operation (genauso wie Überlauf) abzufragen!
➽ Erweiterung des Definitionsbereichs D∗ =D∪{⊥} mit einem künstlichen Element ⊥
(genannt Bottom/undefiniertes Element) und des Wertebereichs W ∗ =W∪{⊥}
Beispiel Division
Totalisierung ist Tripel hℵ∗ ×ℵ∗ ,ℵ∗ ,Ri mit R={...,hh7,0i,⊥i,hh7,1i,7i,...}.
Seite 56
Dr. Stefan Bosse •
Grundlagen der Informatik (B)
Programmiersprachen :: Funktionen (III)
Zentrale Operationen mit Funktionen
Applikation f(x)
Die Applikation liefert dasjenige Element y (möglicherweise ⊥), das im Funktionsgraph x
zugeordnet ist, d.h. hx,yi ∈ Rf
Beispiel:
f: x → y mit y(x)=x-1 und h1,0i
Komposition h = f • g
Bildung einer neuen Funktion h, für die für alle Werte x gilt:
h(x) = (f • g)(x)=f(g(x))
Dr. Stefan Bosse •
Seite 57
Grundlagen der Informatik (B)
Programmiersprachen :: Ausdrücke & Funktionen (I)
➤ Ein elementarer Ausdruck, auch Grundterm genannt, setzt sich zusammen aus:
Konstanten
Konstante Werte eines bestimmten Datentyps, z.B. ganze Zahlen {0,1,2,...}, Gleitpunktzahlen, Textzeichen usw. Ein Konstante kann mit einem symbolischen Name ausgedrückt werden, der einmalig mit einem Wert durch das Schlüsselwort DEF definiert wird,
und an Stelle des Wertes im folgenden Kontext nach der Definition verwendet werden
kann:
DEF const == value
Beispiel: DEF pi == 3.1415
Funktionen
Geschachtelte Anwendung von Funktionen, wie z.B. der elementaren Sinus-Funktion
oder zusammengesetzten Funktionen.
Mathematische Lamba-Notation von Funktionen
DEF fun == λ par1,par2,... • (Implementierung)
➽ Funktionsparameter werden in der Funktionsimplementierung verwendet.
Beispiel:
DEF grad == λ r • (r/(2.0*pi)*360.0)
DEF pyth == λ a,b • (a*a+b*b)
Seite 58
Dr. Stefan Bosse •
Grundlagen der Informatik (B)
Programmiersprachen :: Ausdrücke & Funktionen (II)
➤ Die Lambda-Notation ist eine weit verbreitete universelle Notation für funktionale Systeme,
ursprünglich ein Notation aus der Mathematik (ca 1908). Imperative Programmiermodelle
besitzen aber ebenfalls funktionale Konzepte, d.h. die Lambad-Notation ist grundsätzlich
universell.
➤ Der Rumpf einer Funktionsdefinition ist die eigentliche Implementierung und Beschreibung
der Funktionsweise, wie Eingabedaten, also die Funktionsparameter, auf Ausgabedaten, die
Ergebnisse, abgebildet werden.
Die Funktionsparameter sind an den Funktionsrumpf gebunden (λ-Bindung), d.h. nur dort
verwendbar, und sind nicht nach außen sichtbar, man nennt sie verschattet!
➤ Wird eine Funktion angewendet (≡ aufgerufen), wir den Funktionsparametern durch die
Funktionsargumente ein Wert zugewiesen.
Beispiel:
DEF phyth2 == λ x,y •
LET xg == grad(x) IN
LET yg == grad(y) IN
(xg*xg+yg*yg)
➤ Innerhalb einer Funktionsdefinition können neue symbolische Variablen, denen nur einmalig ein Wert oder Ausdruck zugewiesen wird, mittels des Schlüsselwortes LET erzeugt
werden. Symbolische Variablen dienen nur zur Vereinfachung von Ausdrücken ➽ Substitution!
Dr. Stefan Bosse •
Seite 59
Grundlagen der Informatik (B)
Programmiersprachen :: Ausdrücke & Funktionen (III)
Prinzip der Programmierung
Benutze nie Konstanten (mit Ausnahme trivialer Werte wie 0,1,2...) direkt in Ausdrücken,
sondern führe Namen für sie ein!
➤ Von großer Bedeutung für die Lesbarkeit wird bei einigen Funktionen die Infix-Notation verwendet, d.h. die Funktion steht zwischen ihren (zwei) Argumenten. Beispiel sind die arithmetischen Operationen:
DEF add == λ a,b • a + b
... LET y1 == add (2,3) IN
... LET y2 == 2 + 3 IN
⇒ Postfix−Notation
⇒ Infix−Notation
➤ Zur Generalisierung betrachtet man Konstanten als Funktionen nullter Ordnung, d.h. Funktionen, die kein Argument erwarten, und bereits zum Zeitpunkt der Definition vollständig
evaluiert sind.
➤ Neu eingeführte Funktionen können in den Definitionen anderer Funktionen benutzt werden.
➤ Man unterscheidet:
1. die Reihenfolge der Definitionen ist maßgeblich, d.h. eine Funktion darf erst dann angewendet werden, nachdem sie definiert wurde {C,OCAML,PASCAL},
2. die Reihenfolge der Definitionen spielt keine Rolle!
Seite 60
Dr. Stefan Bosse •
Grundlagen der Informatik (B)
Programmiersprachen :: Ausdrücke & Funktionen (IV)
Definitions- und Wertebereiche: Typisierung
Zweck der Typisierung ist es, Programmierfehler möglichst frühzeitig im Entwicklungsprozeß
aufzudecken und sie möglichst exakt klassifizieren zu können!
➤ Ideal wäre eine Typisierung des echten Definitions- und Wertebereiches. Zum Beispiel sind
reale Datentypen in ihrer Wertemenge eingeschränkt. Beispiel: 32 Bit Integer. Oder ein Datentyp wird ausschließlich für Abzählungszwecke verwendet (Beispiel: Anzahl von Studenten in einem Kurs, Wertemenge festgelegt auf {5,6,...,100}.
Eine solche exakte Charaktersierung unterstützen nur wenige Programmiersprachen.
➤ Typisierung wird auf Funktionen angewendet: Definitions- und Wertebereich.
Dazu wird das Schlüsselwort FUN verwendet. Diese gibt eine Typ-Deklaration der Funktionsschnittstelle an (Signatur), analog der mathematischen Schreibweise:
FUN fun: par1typ × par2typ ... → ergebtyp
Beispiele:
FUN sq : int → int
FUN pyth : real × real → real
➤ Der Definitions- und Wertebereich können nicht nur aus elementaren Mengen bestehen (ein
Funktionsparameter), sondern auch aus Produkten von Mengen (Anzahl Funktionsparameter > 1).
➤ Elementare Typmengen: {nat,int,real,char,string,...}
Dr. Stefan Bosse •
Seite 61
Grundlagen der Informatik (B)
Programmiersprachen :: Ausdrücke & Funktionen (V)
Funktionstypisierung: Definitions- und Wertebereiche
Name
sq
pyth
pi
Def.bereich
Wertebereich
int
real×real
int
real
real
Bestandteile von Funktionsdefinitionen
Name
sq
pyth
pi
Parameter
Rumpf
x
a,b
x*x
a*a+b*b
3.1415
➤ Als Grenzfall von Funktionen wurden Konstanten eingeführt. Diese besitzen einen leeren
Definitionsbereich und keine Parameter!
Seite 62
Dr. Stefan Bosse •
Grundlagen der Informatik (B)
Programmiersprachen :: Bedingte Ausdrücke (I)
Bedingte Ausdrücke
Entscheidungen zu treffen ist eine der zentralen Aktivitäten bei der Lösung von Problemen.
Fallunterscheidungen sind bereits aus der Mathematik bekannt:
max(a, b) =
a, f alls a ≥ b
b, sonst
(1)
➤ Diese Schreibweise der Mathematik wird in Programmiersprachen ähnlich beschrieben. Dazu wird für eine dual Fallunterscheidung das IF-THEN-ELSE-Konstrukt verwendet:
IF bool_expr THEN expr_true ELSE expr_false FI
Beispiel
DEF max == λ a,b • IF a ≥ b THEN a ELSE b FI
➤ Die Bedingung ist ein boolescher Ausdruck der entweder den Wert true oder false hat.
Der Typ solcher Ausdrücke ist bool.
➤ Die Ausdrücke im THEN- und ELSE-Zweig müssen Werte des gleichen Typs zurückgeben.
➤ Der Ausdruck expr_true wird ausgeführt wenn bool_expr=true, expr_false bei
bool_expr=false!
Dr. Stefan Bosse •
Seite 63
Grundlagen der Informatik (B)
Programmiersprachen :: Bedingte Ausdrücke (II)
Bewachte Ausdrücke
Häufig steht man vor der Notwendigkeit, mehr als zwei Fälle zu unterschieden. Dazu können
bedingte Ausdrücke geschachtelt werden.
➤ Beispiel
DEF sign == λ x • IF x > 0 THEN +1
ELSE
IF x = 0 THEN 0
ELSE −1
FI
FI
➤ Die Lesbarkeit von geschachtelten Fallunterscheidungen ist gerade bei einer großen Anzahl
von Fällen unübersichtlich! Sinnvoller ist die gleichberechtigte Mehrfach-Fallunterscheidung:
DEF sign == λ x • IF x > 0 THEN +1
IF x = 0 THEN 0
IF x < 0 THEN −1 FI
Seite 64
Dr. Stefan Bosse •
Grundlagen der Informatik (B)
Programmiersprachen :: Bedingte Ausdrücke (III)
Bewachte Ausdrücke (Forts.)
➤ Mehrere Fälle können gleichberechtigt nebeneinander formuliert werden, d..h mat eine FallListe. Diese Variante muß aber folgende Eigenschaften erfüllen:
1. Die Bedingungen (Wächter oder Guards genannt) sollten paarweise disjunkt sein, d.h.
nicht gleichzeitig gelten,
2. die Bedingungen sollten vollständig sein; es sollte also nie vorkommen, daß keiner der
Fälle/Guards gilt (undefiniertes Verhalten!)
➤ Neben dieser universellen bewachten Fallunterscheidung gibt es noch wertebasierte Fallunterscheidungen, sog. Musteranpassung (pattern matching):
_:
MATCH expr_cond WITH
Beschreibt
vollständige
val1 => expr_val1
Wertemenge eines Typs
| val2 => expr_val2
➽ anonyme Variable,
| _ => expr_others
Wildcard-Notation!
x:
➤ Beispiel:
Variable
enthält
alle
sonstigen
Fälle
von
n!
DEF text == λ n • MATCH n WITH
1 → ”one”
| 2 → ”two”
| x → IF x > 0 THEN ”pos” ELSE ”neg”
| _ → ”others”
Seite 65
Dr. Stefan Bosse •
Grundlagen der Informatik (B)
Programmiersprachen :: Bedingte Ausdrücke (IV)
Bedingte Ausdrücke im Flußdiagramm
Seite 66
Dr. Stefan Bosse •
Grundlagen der Informatik (B)
Programmiersprachen :: Strukturieren durch Teilausdrücke
➤ Ein wichtiges Hilfsmittel, um große und unübersichtliche Ausdrücke zu strukturieren, besteht
darin, abkürzende Bezeichnungen für Teilausdrücke einzuführen, ähnlich in der Mathematik.
➤ Lokale Deklaration:
◆ Die abkürzenden Namen werden als lokale Deklarationen eingeführt, entweder in der
Form LET ... IN ... vor der Anwendung oder in der Form ... WHERE ... nach der Anwendung.
◆ Die Definition eines Namens kann sich auf andere lokal deklarierte Namen inklusive gebundenn Funktionsparametern beziehen, die Verwendung ist nur innerhalb des lokalen
Kontext der Funktion möglich!
◆ Die Reihenfolge der Deklaration spielt i.A. keine Rolle, es dürfen aber keine zyklischen
Abhängigkeiten entstehen.
➤ Beispiel: Berechnung der Fläache eines Dreiecks nach der Heron’schen Formel
F∆ =
p
s(s − a)(s − b)(s − c) mit s =
a+b+c
2
(2)
FUN heron : real × real × real → real
DEF heron == λ a,b,c • LET s == (a+b+c)/2 IN
sqrt(s*(s−a)*(s−b)*(s−c))
DEF heron == λ a,b,c • sqrt(s*(s−a)*(s−b)*(s−c))
WHERE s == (a+b+c)/2
Dr. Stefan Bosse •
Seite 67
Grundlagen der Informatik (B)
Programmiersprachen :: Tupel von Ausdrücken
➤ Die Bildung von Tupelausdrücken oder Tupeltermen dient der anonymisierten Bindung und
Strukturierung von Ausdrücken bzw. Elementen.
➤ Sie erfolgt durch Bindung von Ausdrücken in einem Klammerpaar, wobei die einzelnen Ausdrücke bzw. Elemente durch Kommas getrennt werden.
➤ Tupelausdrücke sind z.B. eine Liste von Funktionsargumenten, können aber auch von Funktionen als Wertemenge zurückgegeben werden! Wird naber nur von einigen wenige Programmiersprachen unetrstützt (OCAML).
➤ Ein Tupel ist eine Gesamtheit, und kann in einzelne Ausdrücke oder Elemente mittels Musteranpassung (pattern matching) wieder zerlegt werden:
LET t == (a1,a2,a3,...) IN
LET (b1,b2,b3,...) == t IN ⇔ MATCH t WITH (b1,b2,b3,...) → ...
Beispiele:
FUN sqrts : real → real × real
DEF sqrts == λ x • (sqrt(x), −sqrt(x))
DEF (sq1,sq2) == sqrts(2.0)
DEF sq12 == sqrts(2.0)
...
LET (s1,s2) == sq12 IN
...
FUN min : real × real
→ real
DEF min == λ a,b • IF a > b THEN b ELSE a
Seite 68
Dr. Stefan Bosse •
Grundlagen der Informatik (B)
Programmiersprachen :: Polymorphie
➤ Sinn einer Typsisierung von Ausdrücken und Funktionen ist die Erkennung von Programmierfehlern.
➤ Häufig kann es aber sinnvoll sein, Funktionen bei deren Definition noch nicht auf einen konkreten Typ zu binden, sondern dieses erst bei der Anwendung durchzuführen.
➤ Beispiel sind arithmetische Operator-Funktionen wie die Addition, die wenigstens auf den
Datentyp INT und REAL anwendbar sind.
➤ Bei einer strengen und konkreten Typisierung müsste man aber zwei Funktionen definieren,
jeweils für den entsprechenden Datentyp:
FUN add_int : int × int → int
FUN add_real : real × real → real
DEF X == add_int 1 2; DEF Y == add_real pi 2.0
➤ Praktischer ist die Definition einer universellen Funktion, die auf verschiedene Datentypen
angewendet werden kann, man spricht von polymorphen Funktionen (Polymorphie).
FUN add : α × α → α
DEF X == add 1 2; DEF Y == add pi 2.0
➤ Der polymorphe Typ α (bzw. jeder griechische Buchstabe) umfaßt eine nicht näher spezifizierte Datentypmenge, z.B. {INT,REAL}.
Dr. Stefan Bosse •
Seite 69
Grundlagen der Informatik (B)
Programmiersprachen :: Funktionen höhere Ordnung
➤ Bisher wurden nur Funktionen erster Ordnung betrachtet, d.h. Funktionsargumente und
Ergebniswert der Funktion waren elementare (oder zusammengesetzte) Datentypen.
➤ Ein generisches Funktionsmodell erweitert den Definitions- und Wertebereich um Funktionen
als Funktionsparameter ➽ Funktionen höherer Ordnung.
➤ D.h. Funktionen können als Argumente übergeben, und auch wieder als Ergebnisse zurückgegeben werden, d.h. es können neue Funktionen über Funktionsargumente gebildet werden!
➤ Imperative Sprachen unterstützen i.A. nur Funktionen erster Ordnung, funktionale hingegen
auch höherer Ordnung.
➤ Beispiele
(*) : α × α → α
sin : real → real
sq == λ x • x*x
sq : α → α
sqsin == sq (sin)
≡ λ x • sin(x)*sin(x)
FUN sqsin : real → real
DEF Z == sqsin pi
FUN
FUN
DEF
FUN
DEF
Seite 70
Dr. Stefan Bosse •
Grundlagen der Informatik (B)
Programmiersprachen :: Rekursion
➤ Rekursion bildet das wichtigste Prinzip bei der Formulierung von Algorithmen. Dabei wird das
gleiche Berechnungsmuster geschachtelt immer wieder angewendet, allerdings jedesmal auf
eine reduzierterer Menge von Daten, bis nur noch ein elementares Datum vorliegt.
➤ Bei rekursiven Funktionen kann eine Funktion sih in ihrem Funktionsrumpf selbst aufrufen.
➤ Klassisches aber ”langweiliges” Beispiel: die Fakultätsfunktion, die mathematisch ausgedrückt als Iterationsgleichung lautet:
Mathematisch: fac(n)=fac(n−1)*n
FUN fac: nat → nat
DEF fac == λ n • IF n = 0 THEN 1 ELSE n*fac(n−1) FI
➤ Eine rekursive Funktion bedarf eines Terminierungskriteriums, ansonsten hat man eine endlose Verschachtelung von Funktionen, die bei einer Maschine zu einem Speicherfehler führen
muß (endlicher Speicher, Funktionsaufrufe benötigen jedesmal Speicherplatz), im Beispiel ist
es der bedingte Ausdruck mit der booleschen Bedingung n=0.
➤ Beispiel:
fac(3) ⇒
fac(2) ⇒
fac(1) ⇒
fac(0) ⇒
3*2
2*1
1*1
1
⇔ fac(fac(fac(fac(0))))
Dr. Stefan Bosse •
Seite 71
Grundlagen der Informatik (B)
Programmiersprachen :: Datenstrukturen
➤ Datenstrukturen dienen zur strukturierten Verabeitung und Handhabung von Daten.
➤ Datenstrukturen sind wie Typen reine Programmierparadigmen (∈ Programmiermodell), und
finden sich im Maschinenprogramm nicht wieder!
➤ Konstruktion von Datenstrukturen setzen sich wie bei Funktionen aus elementaren Konstruktionsprinzipen zusammen:
Funktionen
◆
◆
◆
◆
Funktionsapplikation
Tupelbildung
Fallunterscheidung (bedingte Ausdrücke)
Rekursion
Datenstrukturen
◆
◆
◆
◆
Produktbildung ➽ Tupelbildung, Aggregation
Summenbildung ➽ Variantenbildung
Aufzählung
Rekursion
➤ Prinzip der Programmierung: Arbeite intensiv mit Datentypen! Wo immer logisch zusammenhängende Werte im Programm auftreten, sollte man für sie einen eigenen Typ
einführen!
Seite 72
Dr. Stefan Bosse •
Grundlagen der Informatik (B)
Programmiersprachen :: Datenstrukturen :: Produktbildung (I)
➤ Logisch zusammenhängende Daten werden in einer Gruppe namentlich und typisiert zusammengefaßt durch Einführung einer neuen Datenstruktur.
➤ Diesen Vorgang bezeichnet man als Aggregation. Da neue Typen, und nicht neue Datenobjekte definiert werden, wird anstelle des DEF Schlüsselwortes TYPE verwendet:
TYPE typename == Constr(el1: el1type, el2: el2type,...)
TYPE point == Point(x: real, y: real)
TYPE circle == Circle(center:point, radius: real)
TYPE datum == Datum(tag:char, monat:string, jahr:nat)
➤ Es können Daten mit verschiedenen Datentypen zusammengefaßt werden. Jedes Strukturelement ist im Gegensatz zum anonymen Tupel namentlich bezeichnet.
➤ Durch die Deklaration eines neuen Produkttyps wird implizit erzeugt:
Sorte (typename)
Der neue Typname, in den Beispielen point und datum.
Konstruktorfunktion (constr)
Eine Funktion, die ein neues Datenobjekt von diesem Typ erzeugt, in den Beispielen
gleichnamig Point und Datum:
FUN Point : real × real → point
FUN Datum : char × string × nat → datum
Dr. Stefan Bosse •
Seite 73
Grundlagen der Informatik (B)
Programmiersprachen :: Datenstrukturen :: Produktbildung (II)
➤ Durch die Deklaration eines neuen Produkttyps wird implizit erzeugt (Fortsetz.):
Selektorfunktionen/operatoren (el1,...)
Funktionen (Operatoren), mit denen die einzelnen Strukturelemente el1, el2, ... in Ausdrücken ausgewählt werden können, in den Beispielen x,y,tag...:
FUN x: point → real
FUN y: point → real
FUN tag : datum → char
Beispiele:
DEF p == Point(x=10.0,y=20.0)
DEF s == sq(x(p))+sq(y(p))
Die Verwendung von Selektorfunktionen kann durch eine isomorphe vereinfachte Darstellung ersetzt werden (z.B. ML, C):
FUN sel : typeobj → element
⇔
typeobj.sel
Beispiele:
DEF s == sq(p.x)+sq(p.y)
Seite 74
Dr. Stefan Bosse •
Grundlagen der Informatik (B)
Programmiersprachen :: Datenstrukturen :: Produktbildung (III)
➤ Beispiel
(* Typdeklaration *)
TYPE point == Point(x: real, y: real, col: int•int•int)
TYPE circle == Circle(center:point, radius: real)
(* Anmerkung: int•int•int ist ein anonymes Datentupel *)
(* Definition von Datenobjekten *)
DEF p1 == Point(x=10.0,y=20.0,col=100,100,100)
DEF p2 == Point(x=20.0,y=10.0,col=100,100,100)
DEF c == Circle(center=p1,radius=10.0)
DEF is_gray == λ p •
LET (c1,c2,c3) == col(p) IN
c1 = c2 AND c1 = c3 AND c2 = c3
FUN is_gray : point → bool
DEF p1_gray == is_gray(p1)
DEF p2_col == NOT (is_gray(p2))
FUN set_color : int•int•int → unit (* setzt Zeichenfarbe *)
FUN linto : real × real → unit (* zeichnet Linie *)
DEF draw == λ c •
LET c = center(c) IN
set_color(col(c));
lineto(x(c),y(c))
Seite 75
Dr. Stefan Bosse •
Grundlagen der Informatik (B)
Programmiersprachen :: Datenstrukturen :: Summenbildung (I)
➤ Zusammenfassung von Elementen in einem Typ, die inhaltlich Gemeinsamkeiten besitzen
(Semantik), aber strukturell verschieden aufgebaut sind.
➤ Beispiel: Zusammenfassung von Zahlen der Typen {nat,int,real} zu einem übergeordneten Typ zahl.
➤ In diser Situation lassen sich die Elemente des Typs in verschiedenen Varianten klassifizieren
(disjunkte Vereinigung im Sinne der Mengenlehre):
TYPE typname ==
Constr1(el11:el11typ, el12:el12typ ...)
| Constr2(el21:el21typ, ...)
...
| ConstrN(elN1:elN1typ, ...)
Beispiele:
TYPE figure == Line(l1: point, l2: point)
| Circle(center: point,radius: real)
| Rect(c1: point, c2: point)
TYPE zahl == Real(real) | Nat(nat) | Int(int)
DEF r1 == Real(3.14); DEF i1 == Int(10);
Seite 76
Dr. Stefan Bosse •
Grundlagen der Informatik (B)
Programmiersprachen :: Datenstrukturen :: Summenbildung (II)
➤ Die Angabe eines Elementnamens bei einem einzigen Typelement kann optional sein (z.B.
Typ zahl).
➤ Die Anwendung solcher Summentypen in Ausdrücken erfordert explizite oder implizite musterbasierte Ausdrücke bzw. Funktionen mit dem MATCH-Konstrukt:
DEF farbe == λ f •
MATCH f WITH
Line (l,_) → col(l)
| Circle (c,_) → col(c)
| Rect(c,_) → col(c)
FUN add_real: real×real→real;FUN add_int: int×int→int
FUN add_nat: nat×nat→nat
DEF add0 == λ a,b •
MATCH a WITH
Real(ra) →
MATCH b WITH
Real(rb) → add_real(ra,rb)
| _ → ERROR!
| Int(ia) →
MATCH b WITH
Int(ib) → add_int(ia,ib)
| _ → ERROR!
...
Seite 77
Dr. Stefan Bosse •
Grundlagen der Informatik (B)
Programmiersprachen :: Datenstrukturen :: Aufzählungen
➤ Einführung eines neuen Aufzählungs-Typs, der aus einer (kleinen) Anzahl von symbolischen
Elementen besteht.
➤ Entspricht dem Summentyp, wobei alle Typelemente vom gleichen (elementaren) Datentyp
(oder abstrakt) sind, und die einzelnen Typelemente nur durch einen Werte oder Namen
repräsentiert werden.
➤ Auch hier sind musterbasierte Ausdrücke anwendbar, es können aber auch direkte Wertvergleiche bzw. Diskriminatorfunktionen ? verwendet werden.
➤ Beispiel:
TYPE day == montag | dienstag | mittwoch | donnerstag
freitag | samstag | sonntag
TYPE nums == 1 | 2 | 3 | 4
TYPE switch == ”On” | ”Off”
TYPE color == red | blue | green
DEF mycol == red
DEF is_red == λ col •
MATCH col WITH
red → true
| blue | green → false
DEF is_red2 == λ col •
IF col = red THEN ”Yes it0 s red” ELSE ”Other color”
DEF is_red3 == λ col •
IF red?(col) THEN ”Yes it0 s red” ELSE ”Other color”
Seite 78
Dr. Stefan Bosse •
Grundlagen der Informatik (B)
Programmiersprachen :: Datenstrukturen :: Arrays (I)
➤ Arrays sind Produkttypen, hier aber beschränkt auf Elemente vom gleichen Datentyp!
➤ Das Programmiermodell eines Arrays hat seinen Urpsprung im speicherbasierten (imperativen) Programmiermodell, sie sind ein Zugeständnis an die Neumann-Rechnerarchitektur.
➤ Ein Array ist dabei in eine Anzahl N von Datenzellen (≡Elemente gleichen Datentyps) unterteilt (wie ein Datenspeicher), die einzeln selektiert werden können. Ein Array wird daher
i.A. direkt im Programmspeicher der Maschine abgebildet, und einzelne Arrayzellen können
mittels einfacher Adreßrechnung erreicht werden.
E1
WR ➽
➽ RD
E2
···
EN
➤ Man kann Arrays aber auch als spezielle Funktionen auffassen!
Der Definitionsbereich (d.h. der Wertebereich des Funktionsparameters) setzt sich aus Intervallen der ganzen Zahlen zusammen, z.B. {1,2,3,...,N}. Der Startindex kann aber belibieg
sein, abhängig von der Programmiersprache (C fordert generell für I 1 =0!).
Arrays sind aber statische Funktionen die als tabellarische Auflistung ihrer Werte vorliegen.
Dr. Stefan Bosse •
Seite 79
Grundlagen der Informatik (B)
Programmiersprachen :: Datenstrukturen :: Arrays (II)
➤ Der Inhalt von Arrayelementen kann jederzeit verändert werden, so daß ein Array den Zustand eines Programms bestimmt, und daher imperativen Charakter, und nicht funktionalen
Charakter besitzt! Arrays machen i.A. nur Sinn mit Variablen und Schleifenkonstrukten in imperativen Programmiermodellen.
➤ In funktionalen Sprachen müssen daher Arrays immer mit Werten initialisiert werden, da das
Programmiermodell immer gültige Werte von Variablen und Ausdrücken verlangt! Ein nicht
initialisertes Array (wie z.B. in C üblich) ist undefiniert in einem funktionalen und nicht zustandsorientierten Kontext.
➤ Definition eines Arrays:
TYPE Array α
ARRAY arname == artype[interval] := {INIT}
interval == A TO | DOWNTO B
Beispiele:
ARRAY data == real[1 TO 4] := {0.0,0.0,0.0,0.0}
VAL data : Array real
DEF nilpt == Point(x=0.0,y=0.0,col=0,0,0)
ARRAY points == point[0 TO 99] := ALL nilpt
➤ Elementselektion in Ausdrücken:
arname.[index] == get(array,index)
DEF x1 == data.[2] == get(data,2)
Seite 80
Dr. Stefan Bosse •
Grundlagen der Informatik (B)
Programmiersprachen :: Variablen (I)
➤ Bisherige Ausdrücke waren konstant in ihrem Wert oder variabel mit Funktionen durch deren
Funktionsparameter.
➤ Streng genommen sind wertverändernde Anwendungen auf einzelne Zellen von Arrays im
funktionalen Modell keine Änderungen der Werte von Zellen, sondern jede Änderung eines
Arrayelements führt zur Erzeugung eines komplett neuen Arrays:
update(array,index,value) , array.[index] := value
FUN update : Array α × nat × α → Array α
... LET data0 == update(data,2,3.0) IN ...
➤ Erst im Speichermodell können einzelne Elemente eines Arrays verändert werden:
set(array,index,value) == array.[index] := value
FUN set : Array α × nat × α → unit
... data.[2] := 3.0 ...
➤ Da in der Realität durch einen Compiler aus einem Programm das mit einem funktionalen
Modell beschrieben wird ein Maschinenprogramm wird, bleibt es dem Compiler überlassen,
wie er mit dieser Situtaion umgeht (Optimierung; Erzeugung von neuen Datenobjekten ist
eine teure Operation: Speicher, Laufzeit)
Dr. Stefan Bosse •
Seite 81
Grundlagen der Informatik (B)
Programmiersprachen :: Variablen (II)
➤ Variablen können äquivalent zu Arrays auf zwei Arten modelliert werden:
Referenzvariablen
Durch Referenzen auf Datenobjekte bzw. Ausdrücke/Elemente, in Anlehnung an das
funktionale Modell, wo Datenobjekete unveränderlich sind, und nur die Referenz variabel
ist, aber immer auf ein vorhandenes Datenobjekt verweist (Zeiger):
DEF refvar == REF value
DEF x == REF 0
... LET a == 1 IN x := a; LET b == !x + 1 IN ...
⇒ ≡ x == REF a
➥ Im Beispiel enthält x einen Zeiger zuerst auf den konstanten Wert 0, dann auf den
Ausdruck (unveränderliche ”Variable”) a.
Speichervariablen
Durch echte veränderliche Ausdrücke/Elemente, die nur mit dem Speichermodell beschrieben werden können.
DEF realvar == VAR value
DEF x == VAR 0
... LET a == 1 IN x ← a; LET b = x + 1 IN ...
⇒ ≡ x == a == 1
Seite 82
Dr. Stefan Bosse •
Grundlagen der Informatik (B)
Programmiersprachen :: Variablen (III)
Dr. Stefan Bosse •
Seite 83
Grundlagen der Informatik (B)
Programmiersprachen :: Schleifen und Rückwirkung
➤ Rein funktionale Modelle beschreiben Datenpfade, d.h. Abhängigkeiten und Zusammenhänge von Daten und Ausdrücken. Iterative Abarbeitung eines Problems mittels Funktionen und
Funktionsrekursion.
➤ Imperative Programmierung bedeutet zusätzlich Beschreibung von Kontrollpfaden, d.h. der
Ablaufsteuerung eines Programms.
➤ Imperative Programmierung kennt neben Funktionen noch Schleifen (des Kontrollflusses!) als
ein Mittel, ein Programmteil (-block) wiederholt auszuführen:
Zählschleife
Eine Schleife mit einem Schleifenzähler, der bei jedem Durchlauf des Schleifenblocks
inkrementiert oder dekrementiert wird. Der Wert des Schleifenzählers kann im Schleifenblock abgerufen werden.
FOR i = a TO b DO ... DONE;
Bedingte Schleife
Ein Schleifenblock wird solange wiederholt ausgeführt, bis eine Abbruchbedingung
(boolescher Ausdruck) erfüllt ist.
WHILE expr DO ... DONE;
Seite 84
Dr. Stefan Bosse •
Grundlagen der Informatik (B)
Programmiersprachen :: Bedingte Schleife (I)
➤ Eine bedingte Schleife führt Anweisungen A1,A2,... im Schleifenblock S wiederholt aus, solange ein boolescher Ausdruck B im Schleifenkopf den Wert wahr ergibt.
WHILE B
DO
A1;
A2;
...
DONE;
➤ Beispiel:
LET i = VAR 0 IN
WHILE i < 3
DO
i ← i + 1;
DONE;
⇔
i ← i+1;
(* i == 1 *)
i ← i+1;
(* i == 2 *)
i ← i+1;
(* i == 3 *)
Dr. Stefan Bosse •
Seite 85
Grundlagen der Informatik (B)
Programmiersprachen :: Bedingte Schleife (II)
➤ Eine bedingte Schleife setzt Speichervariablen und das Speichermodell voraus, da bei der
Schleifeniteration eine Zustandsänderung des Schleifenausdruckes erreicht werden muß.
➤ Bisher konnten Werte von Ausdrücken nur nach deren Zuweisung abgerufen werden. Bei einer Schleife muß es aber eine Rückwirkung geben, da der Schleifenausdruck (Zeile 1) VOR
der zustandsverändertenden Zuweisung (Zeilen 4,5) auftritt (man spricht auch von Seiteneffekten):
0:
1:
2:
3:
4:
5:
6:
LET i,j,k,... = VAR 0 IN
WHILE exprS(i,j,k,...)
exprS: bool. Ausdruck mit i...
DO
...
i ← exprI;
exprI: neuer Wert von i
j ← exprJ;
DONE;
➤ Beispiel:
LET i,j = VAR 0 IN
WHILE (i+j) < 10
DO
i ← i + 1;
DONE;
Seite 86
(* i == 0
*)
(* i und j werden gelesen *)
(* i wird verändert, j nicht! *)
Dr. Stefan Bosse •
Grundlagen der Informatik (B)
Programmiersprachen :: Bedingte Schleife (III)
➤ Das letzte Beispiel zeigt die Problematik und die Risiken von Schleifen bei der Programmierung:
◆ Die Abbruchbedingung B=false kann von einer Vielzahl von Variablen abhängen, die
sich auf verschiedenste Weise durch Ausdrücke innerhalb des Schleifenkörpers ändern
können.
◆ Das Terminierungskriterium B=false ist im Gegensatz zur Funktionsrekursion nicht direkt
ersichtlich, insbesondere die Frage der Erfüllbarkeit ist durch die Wertrückwirkung nicht
immer beantwortbar.
◆ Das führt zur Gefahr von Endlosschleifen, bei denen das Terminierungskriterium niemals erfüllt ist:
LET i,j = VAR 0 IN
WHILE j < 10
DO
i ← i + 1;
DONE;
(* i == 0
*)
(* j wird gelesen *)
(* i wird verändert, j nicht! *)
Dr. Stefan Bosse •
Seite 87
Grundlagen der Informatik (B)
Programmiersprachen :: Zählschleife (I)
➤ Eine Zählschleife führt Anweisungen A1,A2,... im Schleifenblock S wiederholt aus, solange
sich ein Schleifenzähler I innerhalb eines vorgegebenen Intervalls befindet, d.h. es gibt indirekt einen booleschen Ausdruck B im Schleifenkopf und einen Ausdruck E am Ende des
Schleifenblocks S, der den Schleifenzähler inkrementiert oder dekrementiert:
FOR I = A TO | DOWNTO B hSTEP Di
DO
A1;
A2;
...
DONE;
➤ Der Schleifenzähler ist innerhalb des Schleifenblocks als lokale Variable verfügbar (kann gelesen werden).
➤ Beispiel:
FOR i = 1 TO 3
DO
j ← j + i;
DONE;
⇔
j ← j + 1;
j ← j + 2;
j ← j + 3;
Seite 88
Dr. Stefan Bosse •
Grundlagen der Informatik (B)
Programmiersprachen :: Zählschleife (II)
➤ Eine Zählschleife kann in eine bedingte Schleife transformiert werden, indem der Schleifenzähler durch eine Speichervariable (TYP INTEGER) realisiert wird, die Schleifenvariable vor
der Schleife initialisiert wird, und am Ende des Schleifenblocks ein Ausdruck zur Änderung
des Schleifenzählerwertes hinzugefügt wird:
FOR I = A TO | DOWNTO B STEP D
DO
A1;
A2;
...
DONE;
⇔
LET I = VAR 0 IN
I ← A;
WHILE I < B
DO
A1;
A2;
...
I ← I +/− D;
DONE;
(* +:TO −:DOWNTO *)
Dr. Stefan Bosse •
Seite 89
Grundlagen der Informatik (B)
Programmiersprachen :: C [RRZN98]
➤ Die Entwicklung der Programmiersprache C ist eng mit der Entwicklung des Betriebssystems
UNIX verbunden. Die Anfänge sind in den Jahren um 1970 datiert (Dennis Ritchie).
➤ C ist eine klassische imperative Programmiersprache mit mitteleren Abstraktionsgrad bezüglich Maschine und Betriebssystem: basiert auf Speichermodell.
➤ Wichtige Elemente eines C-Programms:
◆
◆
◆
◆
◆
Funktionen
Blöcke
Typen
Anweisungen
Variablen, Arrays und Strukturen (benutzerdefinierte Typen)
➤ Zeichensatz (zulässige Zeichen):
A..Z,a..z,0..9
Leerzeichen, Zeilenendzeichen (NL/CR)
()[]{} <> +−*/ %⊥~&|_=!?#\,.;:0 ”
➤ Bezeichner und Namen:
➥ Bezeichner dienen zur eindeutigen Identifizierung von Objekten in einem Programm. Ein
Objekt ist in C ein Speicherbereich, der aus einer zusammenhängenden Folge von Bytes
bestehen muß.
Seite 90
Dr. Stefan Bosse •
Grundlagen der Informatik (B)
Programmiersprachen :: C (II)
➤ Für Bezeichner in C-Programmen gilt:
◆ Ein Bezeichner besteht aus einer Folge von Buchstaben, Ziffern oder dem _ Zeichen,
wobei das erste Zeichen keine Ziffer sein darf.
◆ Ein Bezeichner darf beliebig lang sein, wobei aber nur eine besteimmte Länge signifikant
ist (abhängig von C-Implementierung/Compiler)
◆ Schlüsselwörter dürfen nicht als Bezeichner verwendet werden.
➤ In C-Programmen sind Name Bezeichner von Variablen, Funktionen und Typen.
➤ Bei Namen unterscheidet man
interne Namen
die nur innerhalb einer Quellcode-Datei gültig und sichtbar sind, und
externe Namen
die im gesamten Programmkontext gültig und sichtbar sind.
➤ Bei
internen Namen
sind die ersten 31 Zeichen signifikant, es wird zwischen Klein- und Großschreibung
unterschieden, bei
externen Namen
sind mindestens die ersten 6 Zeichen signifikant (Unterscheidung Groß- und Kleinschreibung ist abhängig von C-Implementierung).
Dr. Stefan Bosse •
Seite 91
Grundlagen der Informatik (B)
Programmiersprachen :: C :: Typen (I)
➤ C ist eine typsisierte Programmiersprache, d.h. alle in einem C-Programm verwendeten Objekte besitzen einen Typ.
➤ Die Typen von Variablen und Funktionen müssen daher deklariert werden.
➤ Elementare Datentypen:
Integer-Typ int
Verwendung:
1. Ganzzahlige Werte
unsigned int
Kodierung der natürlichen Zahlen ohne Vorzeichen
signed int (default)
Kodierung der ganzen Zahlen (positiv & negativ), 2-er-kompl. Darstellung!
short int
Integer-Zahl mit kleinem Werte-Intervall (i.A. Datenbreite 2 Byte)
long int
Integer-Zahl mit großem Werte-Intervall (i.A. Datenbreite 4-8 Byte)
2. Bit-Vektoren (boolesche Operationen)
3. Boolesche Werte (ersetzt nicht vorhandenen Typ bool). Nur ein Bit wird verwendet!
Seite 92
Dr. Stefan Bosse •
Grundlagen der Informatik (B)
Programmiersprachen :: C :: Typen (II)
➤ Elementare Datentypen (Forts.):
Character-Typ char
➥ Datenbreite entspricht kleinster logischer Speicherzellengröße (1 Byte)
Verwendung:
1. Ganzzahlige Werte
unsigned char
Kodierung der natürlichen Zahlen ohne Vorzeichen, Datenbreite 1 Byte
signed char
Kodierung der ganzen Zahlen (positiv & negativ), 2-er-kompl. Darstellung, Datenbreite 1 Byte!
2. Textzeichen
3. Bit-Vektoren (boolesche Operationen)
4. Boolesche Werte (ersetzt nicht vorhandenen Typ bool). Nur ein Bit wird verwendet!
Fließkomma-Typ float/double/long double
Darstellung reeller Zahlen (positiv&negativ) mit Fließkomma-Darstellung. Datenbreite
i.A. 4 Byte (float) und 8 Byte (double).
Dr. Stefan Bosse •
Seite 93
Grundlagen der Informatik (B)
Programmiersprachen :: C :: Typen (III)
➤ Elementare Datentypen (Forts.):
Leerer Typ void
Der void-Typ ist ein besonderer Typ, er besitzt keinen Wert und auf ihm sind keine
Operationenen definiert. Der Datentyp void steht für eine leere Menge.
Er wird in folgenden Kontext verwendet:
Zeiger
Typ-anonyme Referenzen auf Datenobjekte, d.h. eine Speicheradresse ohne konkreten Datentyp.
Funktionen
Als ”Typangabe” in einer parameterlosen Funktion, d.h. es wird expliziz das Fehlen
von Parametern in einer Funktionsdeklaration angegeben.
Prozeduren
In C gibt es nur Funktionen. Soll eine Funktion keinen Rückgabewert liefern, d.h.
eine Prozedur, muß der Rückgabetyp der Funktion void sein.
Seite 94
Dr. Stefan Bosse •
Grundlagen der Informatik (B)
Programmiersprachen :: C :: Variablen (I)
➤ Variablen sind benannte Datenkontainer, die durch das Speichermodell beschrieben werden.
Eine Variable ist gekennzeichnet durch:
Name oder Referenz
Gültiger Bezeichner zusammengesetzt aus Buchstaben, im Speichermodell eine Speicheradresse im Hauptspeicher.
Behälter
Eigentlicher Datenspeicher der Variable.
Wert
Der Inhalt der Variable.
Typ
Datentyp der Variable. Der Datentyp ist zum einen ein Programmierparadigma, und dient
der Unterstützung des Programmierers zur Vermeidung von Dateninkonsistenzen, zum
anderen bestimmt er die Größe des Speicherbereichs.
➤ Definition und Typdeklaration einer Variablen mit dem Namen v eines bestimmten Datentyps
vartype:
Pseudo−Notation
⇔
C−Notation
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
DEF v == VAR value
⇔
vartype v h=valuei; (Definition)
VAL v : type
⇔
extern vartype v; (Deklaration)
Seite 95
Dr. Stefan Bosse •
Grundlagen der Informatik (B)
Programmiersprachen :: C :: Variablen (IB)
➤ Die Referenz ist unveränderliches Kennzeichen im Gegensatz zum Wert einer Variablen. Die
Referenz bestimmt die Identität einer Variablen.
Es werden zwei Modelle von Variablen unterschieden:
Wert- oder Kopiersemantik
Die Referenz identifiziert umkehrbar eindeutig einer Variable. D.h. zu jeder Referenz
existiert genau ein Behälter. Eine Schreiboperation ändert den Wert der Variable.
Referenzsemantik
Mehrere Referenzen können auf denselben Behälter zeigen. Eine Schreiboperation ändert gleichzeitig den Wert aller durch ihre Referenzen unterschiedenen Variablen, die
auch zuvor den gleichen Wert besaßen.
➤ C unterstützt sowohl Wert wie Referenzsemantik!
D.h. Variablen deren Namensreferenz
eindeutig und einmalig einen Behälter zuordnet, und Variablen mit unterschiedlichen Namensreferenzen, aber
alle auf den gleichen Behälter verweisen ➽ Zeiger (Pointer)
Seite 96
Dr. Stefan Bosse •
Grundlagen der Informatik (B)
Programmiersprachen :: C :: Variablen (II)
➤ Da C-Variablen direkt einem Speicherbereich zugeordnet werden, gekennzeichnet durch
1. die erste Speicheradresse und
2. durch die Größe des Speicherbereichs,
kann die Speicheradresse ℘(v) mittels eines Adreßoperators ermittelt werden:
Pseudo−Notation
⇔
C−Notation
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
?
⇔
vartype v;
(Definition)
&v
(Adresse)
sizeof(v)
(Größe)
➤ Variablen kann ein Wert zugewiesen werden (linke Seite eines Ausdrucks LHS) oder der Wert
einer Variable kann gelesen werden (rechte Seite eines Ausdrucks RHS):
Pseudo−Notation
⇔
C−Notation
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
v ← hexpri;
⇔
v = hexpri;
(Wertzuweisung)
x ← hv∈expri;
⇔
x = hv∈expri;
(Wert lesen)
Dr. Stefan Bosse •
Seite 97
Grundlagen der Informatik (B)
Programmiersprachen :: C :: Variablen (III)
➤ Beispiele
Pseudo−Notation
⇔
C−Notation
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
DEF x == VAR 0
⇔
int x=0;
(Definition)
x ← 0;
⇔
x = 0;
(Zuweisung)
x ← x + 1;
⇔
x = x + 1; (Ausdruck)
➤ Neben den eigentlichen Datenvariablen gibt es explizite Referenzobjekte, die auf ein Datenobjekt zeigen (es referenzieren). In C bezeichnet man solche Referenzobjekte als Zeiger
(Pointer).
➤ Ein Zeiger ist in C selbst eine Variable. Sie besitzt einen
Behälter, der Speicherzellen
belegt! Der Wert des Behälters ist die Speicheradresse
eines Datenobjektes!
Seite 98
Dr. Stefan Bosse •
Grundlagen der Informatik (B)
Programmiersprachen :: C :: Variablen (IV)
➤ Definition, Deklaration und Verwendung von Zeigern:
Pseudo−Notation
⇔
C−Notation
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
DEF x == VAR v0
⇔
vartype x; x = v0;
DEF xr == REF x
⇔
vartype *xp; (Definition Zeiger)
xp=&x;
(Zuweisung Zeiger)
xr := v1;
⇔
*xp = v1; (Wertzuweisung)
DEF y == !xr
⇔
y = *xp;
(Werterhalt)
Deklaration: Bekanntgabe einer Variablen, Name und Datentyp; Definition: Deklaration mit
gleichzeitiger Belegung von Speicherressourcen ➽ Erzeugung des Behälters!
➤ Beispiele:
Pseudo−Notation
⇔
C−Notation
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
DEF u == VAR 3.14
⇔
float u; u=3.14;
DEF ur == REF u
⇔
float *up;
up=&u;
ur := 2*3.14;
⇔
*up = 2*3.14;
DEF y == !ur
⇔
y = *up;
➥ y hat jetzt den Wert 6.28!!!
Dr. Stefan Bosse •
Seite 99
Grundlagen der Informatik (B)
Programmiersprachen :: C :: Lebensdauer von Variablen
➤ Variablen können in C einen begrenzten Kontext besitzen (Lokalität), in denen Variablen
sichtbar sind bzw. Speicherzellen belegen.
Pseudo−Notation
⇔
C−Notation
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
DEF a =
{ /* Block 1 */
LET b = VAR v2 IN
vartype a=v1;
(expr b)
{ /* Block 2 */
...
vartype b=v2;
expr b...
};
...
};
➤ Ein lokaler Kontext wird in C durch ein Klammerpaar {} eingeführt. Die Variable a ist im gesamten nachfolgenden Kontext sichtbar, wird aber im ersten Block durch eine lokale Variable
überdeckt, die Variable b hingegen nur innerhalb des zweiten Programmblockes! Beispiel:
{int a=0;
if (a==0) {int a=2;a=a+2;} else {int b=3;a=b+1;}
};
Seite 100
Dr. Stefan Bosse •
Grundlagen der Informatik (B)
Programmiersprachen :: C :: Zusammengesetzte Datentypen (I)
➤ Einsortige Datenstrukturen: Arrays (Feldtyp) ⇔indizierte Variable.
Definition und Verwendung in Ausdrücken:
Pseudo−Notation
⇔
C−Notation
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
ARRAY name == type[size]
type name[size];
:= {v1,v2,...};
name.[i] ← expr;
name[i] = expr;
LHS ← expr(name.[i]);
LHS = expr(name[i]);
➤ Der Typ eines Feldes ist durch seinen Elementtyp und seinen Indextyp gekennzeichnet. Der
Indextyp muß ein ordinaler Typ sein, d.h. entweder ganzzahlig oder mit diesem verträglich
sein, z.B. eine endliche Menge von Namen {x,y,z,...}.
➥ C unterstützt nur ganzzahlige Werte. Das erste Element eines Arrays hat immer Index 0!
➥ Der Elementdatentyp kann beliebig sein, muß aber bei der Definition festgelegt sein.
i=0
1
2
3
4
Speicheradresse →
5
6
7
≈ Index
Dr. Stefan Bosse •
Seite 101
Grundlagen der Informatik (B)
Programmiersprachen :: C :: Zusammengesetzte Datentypen (II)
➤ Einsortige Datenstrukturen: Arrays (Feldtyp) ⇔indizierte Variable.
Beispiele in C:
int x;
float yr[10];
int ar[100];
char str[8]=”ROBOTIK”;
...
ar[0] = 0;
for(x=1;x<100;x++)
{
ar[x] = ar[x−1] + 1;
};
...
➤ Zeichenketten (strings) können als Felder des Datentyps char dargestellt werden. Zeichenketten werden in C mit einem zusätzlichen End-Of-String (EOS)-Zeichen vom Wert 0 abgeschlossen, d.h. eine Zeichenkette mit 7 Zeichen benötigt 8 Speicherstellen (siehe Beispiel)!
➤ Das EOS wird benötigt um die Länge einer Zeichenkette ermitteln zu können!
Seite 102
Dr. Stefan Bosse •
Grundlagen der Informatik (B)
Programmiersprachen :: C :: Zusammengesetzte Datentypen (III)
➤ Mehrsortige Datenstrukturen: Aggregation ⇔Produktbildung.
Definition eines Strukturtyps und Erzeugung von Objekten dieses Typs:
Pseudo−Notation
⇔
C−Notation
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
TYPE typname == Constr(
struct typname {
el1: type1,
type1 el1;
el2: type2,
type2 el2;
...
...
)
};
◆
struct typname objname
DEF objname == Constr(
el1 = v1,
h{el1=v1,...}i;
el2 = v2,
objname.el1 = v1;
...
...
)
➤ Die neue Typdefinition deklariert nur. Es muß eine Variable von diesem Datentyp explizit
erzeugt werden.
Um auf eine Komponente einer solchen Strukturvariablen zugreifen zu können, wird dem
Variablennamen der Komponentenname angehängt, getrennt durch einen Punkt.
Dr. Stefan Bosse •
Seite 103
Grundlagen der Informatik (B)
Programmiersprachen :: C :: Zusammengesetzte Datentypen (IV)
➤ Mehrsortige Datenstrukturen: Aggregation ⇔Produktbildung.
Beispiele
Pseudo−Notation
⇔
C−Notation
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
TYPE point == Point(
struct point {
x: real,
float x;
y: real,
float y;
col: int•int•int
struct color col;
)
};
◆
struct color { int r;
int g; int b;};
DEF p1 == Point(
struct color gray={100,100,100};
x=1.0,
struct point p1={1.0,2.0,
y=2.0,
gray};
col=100,100,100
);
DEF x == p1.x
float x;
x = p1.x;
Seite 104
Dr. Stefan Bosse •
Grundlagen der Informatik (B)
Programmiersprachen :: C :: Zusammengesetzte Datentypen (V)
➤ Mehrsortige Datenstrukturen: Aggregation ⇔Produktbildung.
Neben Strukturvariablen, die direkt mit einem Variablenbehälter verknüpft sind, kann man
auch Zeiger auf Strukturvariablen definieren:
Pseudo−Notation
⇔
C−Notation
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
TYPE typname == Constr(
struct typname {
el1: type1,
type1 el1;
el2: type2,
type2 el2;
...
...
)
};
◆
DEF objname == REF Constr(
struct typname obj;
el1 = v1,
struct typname *objpointer;
el2 = v2,
objpointer=&obj;
...
...
);
... !objname.elx...
...objpointer→elx...
➤ Ein Zeiger in C ist zunächst uninitalisiert, d.h. ungültig. Der Zeiger muß erst noch mit einem
Objekt verknüpft werden. Die Derreferenzierung findet mit → statt.
Dr. Stefan Bosse •
Seite 105
Grundlagen der Informatik (B)
Programmiersprachen :: C :: Zusammengesetzte Datentypen (VI)
➤ Mehrsortige Datenstrukturen: Aggregation ⇔Produktbildung.
Beispiele mit Zeigern
Pseudo−Notation
⇔
C−Notation
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
TYPE point == Point(
struct point {
x: real,
float x;
y: real,
float y;
col: int•int•int
struct color col;
)
};
◆
struct color { int r;
int g; int b;};
DEF pp1 == REF Point(
struct color gray={100,100,100};
x=1.0,
struct point p1={1.0,2.0,
y=2.0,
gray};
col=100,100,100
struct point *pp1=&p1;
);
DEF x == !pp1.x
float x;
x = pp1→x;
Seite 106
Dr. Stefan Bosse •
Grundlagen der Informatik (B)
Programmiersprachen :: C :: Zusammengesetzte Datentypen (VII)
➤ Mehrsortige Datenstrukturen: Summenbildung.
Summenbildung ist in C auf Aufzählungen von symbolischen Namen beschränkt.
Pseudo−Notation
⇔
C−Notation
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
TYPE name ==
enum name {
el1 |
el1,
el2 |
el2,
...
...
};
➤ Die Symbolliste name wird in C als Integer-Datentyp verwendet. Die symbolischen Namen
werden dabei beginnend mit dem Wert 0 aufsteigend inidiziert, d.h. el1==0, el2==1 ... ➽
Nur der Listentyp Integer wird in C unterstützt.
➤ Bespiele:
Pseudo−Notation
⇔
C−Notation
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
TYPE color ==
enum color {
red | blue | green
red,blue,green};
DEF mycol == red
color mycol; | int mycol;
mycol=red;
Dr. Stefan Bosse •
Seite 107
Grundlagen der Informatik (B)
Programmiersprachen :: C :: Ausdrücke
➤ Ausdrücke in C sind
1. Zuweisungen mit arithmetischen und logischen Ausdrücken; beinhalten das Lesen des
Wertes (rechte Seite RHS) von Variablen und die Wertänderung von Variablen (linke
Seite LHS),
2. boolesche und relationale Ausdrücke, die in Kontrollanweisungen verwendet werden.
Pseudo−Notation
⇔
C−Notation
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
DEF x == expr
{
LET y == expr IN
vartype x;
...
x=expr;
{
vartype y;
y=expr;
➤
➤
➤
➤
Arithmetische Ausdrücke: +,-,*,/,%,...
Boolesche Ausdrücke: &&,||,!,...
Logische Ausdrücke (Bitvektoren): &,|,~,...
Relationale Ausdrücke: <,>,<=,>=,!=,==
Seite 108
Dr. Stefan Bosse •
Grundlagen der Informatik (B)
Programmiersprachen :: C :: Anweisungen (I)
➤ Kontrollanweisungen
Ausdrucksanweisung
Durch Anhängen eines Semikolons wird aus einem Ausdruck eine Anweisung:
ausdruck ;
Block
Ein Block besteht aus Anweisungen, die durch geschweifte Klammern {} eingeschlossen
sind. Ein Block dient der anonymen Bindung (Komposition) von Anweisungen:
{
Deklarationen
Definitionen
Anweisungen
};
➥ Jeder Block kann neben Anweisungen auch Deklarationen und Definitionen enthalten. In einem Block definierte Variablen sind nur innerhalb diese Blocks sichtbar und
gültig (lokaler Kontext).
Dr. Stefan Bosse •
Seite 109
Grundlagen der Informatik (B)
Programmiersprachen :: C :: Anweisungen (II)
➤ Kontrollanweisungen
Bedingte Schleife
Wiederholte Ausführung eines Blocks, solange ein boolescher Ausdruck B=true ist.
Pseudo−Notation
⇔
C−Notation
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
WHILE B
while (B)
DO
{
...
...
DONE;
};
◆
first ← true;
WHILE B OR first
do
DO
{
...
...
first ← false;
DONE;
} while (B);
➥ Bei der do-while-Schleife wird der Schleifenblock mindestens einmal ausgeführt!
Seite 110
Dr. Stefan Bosse •
Grundlagen der Informatik (B)
Programmiersprachen :: C :: Anweisungen (III)
➤ Kontrollanweisungen
Zählschleife
Bestimmte Anzahl von wiederholten Ausführungen eines Blocks,
solange sich eine Indexvariable x innerhalb eines vorgegebenen Werteintervals [a,b]
befindet..
Pseudo−Notation
⇔
C−Notation
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
int x;
FOR x = a to b
for(x=a;x<b;x=x+1)
DO
{
...
...
DONE;
};
◆
for(init,cond,appl)
➥ Die for-Schleife ist eine universelle Schleife wie die while-Schleife mit expliziter Angabe 1. des Initialisierungsausdrucks init, der Durchlaufbedingung cond, und dem
zustandsverändernden Ausdruck appl, der nach jedem Schleifendurchlauf ausgeführt
wird.
➥ Alle drei Ausdrücke im for-Schleifenkopf können auch aus einer Liste von Ausdrücken
gebildet werden: expr1,expr2,...
Dr. Stefan Bosse •
Seite 111
Grundlagen der Informatik (B)
Programmiersprachen :: C :: Anweisungen (IV)
➤ Sprunganweisungen
break
Die break-Anweisung bewirkt, daß die innerste umgebende Schleife sofort verlassen
wird (Ausgangspfad im Kontrollfluß).
Pseudo−Notation
⇔
C−Notation
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
?
break;
continue
Die continue-Anweisung bewirkt, daß der aktuelle Schleifendurchlauf beendet wird
und die Schleife mit der nächsten Iteration fortgesetzt wird.
Seite 112
Dr. Stefan Bosse •
Grundlagen der Informatik (B)
Programmiersprachen :: C :: Anweisungen (V)
➤ Beispiele
int x;
x=0;
while(x<10)
{
x=x+1;
if (x==5) break;
if (x==3) continue;
x=x+1;
};
◆
int y=10;
for(x=0;x<10;x=x+1)
{
y=y−1;
if (y==4) break;
};
Dr. Stefan Bosse •
Seite 113
Grundlagen der Informatik (B)
Programmiersprachen :: C :: Anweisungen (VI)
➤ Auswahlanweisungen ➽ Boolesche Auswahl
Mit Auswahlanweisungen kann der Ablauf von Programmen geändert werden, die Ablaufänderung ist von booleschen Bedingungen oder der Evaluierung und den Vergleich von
Ausdrücken abhängig.
if-then-else
Die Ausführung einer Anweisung oder eines Blocks wird abhängig von dem Ergebnis
eines booleschen oder relationalen Ausdrucks B.
Pseudo−Notation
⇔
C−Notation
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
IF B THEN
if (B)
expr_true
anweisung_true;
ELSE
helse
expr_false;
anweisung_false;i
Beispiel:
Pseudo−Notation
⇔
C−Notation
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
IF b<10 THEN
if (b<10)
b+1
x=b+1;
ELSE
b−1;
Seite 114
Dr. Stefan Bosse •
Grundlagen der Informatik (B)
Programmiersprachen :: C :: Anweisungen (VII)
➤ Auswahlanweisungen ➽ Mehrfachauswahl
select-case
Die Ausführung einer Anweisung oder eines Blocks wird abhängig von dem Ergebnis
eines Vergleichs von Konstanten C={v1,...} mit einem Ausdruck E.
Pseudo−Notation
⇔
C−Notation
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
MATCH E WITH
select E {
| v1 ⇒ a1;
case v1: a1; break;
| v2 ⇒ a2;
case v2: a2; break;
...
| _ ⇒ aN;
default: aN; break;
};
➥ Der letzte Fall default beinhaltet alle Werte R der möglichen Wertemenge
W(E)=C∩R, die nicht durch die beschriebenen Werte v∈C aufgeführt sind.
➥ In C können nur Ausdrücke und Konstanten vom Typ Integer (int) eingesetzt werden!
➥ Jeder Einzelfall muß in C mit der break-Anweisung abgeschlossen werden!
Dr. Stefan Bosse •
Seite 115
Grundlagen der Informatik (B)
Programmiersprachen :: C :: Anweisungen (VIII)
➤ Auswahlanweisungen ➽ Mehrfachauswahl
select-case
Beispiel:
Pseudo−Notation
⇔
C−Notation
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
LET y ==
int b,x,y;
MATCH x WITH
select (x) {
| 1 → b+1;
case 1: y=b+1; break;
| 2 → b;
case 2: y=b; break;
| _ → 0 IN ...
default: y=0; break;
};
...
Seite 116
Dr. Stefan Bosse •
Grundlagen der Informatik (B)
Programmiersprachen :: C :: Funktionen (I)
➤ Funktionen und Prozeduren definieren einen benannten Programmblock A, der aus einzelnen
Anweisungen besteht. In C wird dieser Programmblock durch ein Klammerpaar {} definiert.
➤ Dieser Programmblock A kann durch Nennung des Funktionsnamens an beliebiger Stelle im
Programm wiederholt ausgeführt werden.
➤ Die Zusammenfassung (Komposition) von Anweisungen im Funktionsblock zu einer neuen
Anweisung wird als Prozedurale bzw. funktionale Abstraktion bezeichnet.
➤ Der Funktionskopf spezifiziert:
◆ den Funktionsnamen,
◆ die Funktionsparameter (Name p, Typ ptype in C)
◆ den Rückgabetyp (Ergebnistyp rtype).
Funktionsdefiniton:
Pseudo−Notation
⇔
C−Notation
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
DEF fun == λ p1,p2,...•
rtype fun(ptype1 p1 h,
A...
ptype p2,...i)
{
A...
return (result);
};
Dr. Stefan Bosse •
Seite 117
Grundlagen der Informatik (B)
Programmiersprachen :: C :: Funktionen (II)
➤ Es wird zwischen Funktionsdeklaration (Bekanntgabe der Funktion, Parametertypen und
Rückgabetyp) und Funktionsdefinition unterschieden:
Pseudo−Notation
⇔
C−Notation
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
VAL fun : ptype1 h×
extern rtype fun(ptype1 p1 h,
ptype2...i
ptype p2,...i)
{};
→ rtype
➤ Beispiele
Pseudo−Notation
⇔
C−Notation
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
DEF sq == λ x •
int sq(int x) {
x*x
return (x*x)
};
DEF sum == λ a,b •
float sum(float a,float b){
a+b
float tmp;
tmp=a+b;
return (tmp);
};
Seite 118
Dr. Stefan Bosse •
Grundlagen der Informatik (B)
Programmiersprachen :: C :: Funktionen (III)
➤ Funktionen besitzen in funktionalen und imperativen Programmiersprachen unterschiedliches Programmiermodell:
funktional
Eine Funktion beschreibt Datenabhängigkeiten und Verknüpfungen durch Operationen
und weitere Funktionen, eine Funktion ist am Ende eines Datenpfades implizit beendet.
imperativ
Neben den Datenabhängigkeiten und Verknüpfungen beschreibt eine Funktion den
Kontrollfluß, so daß in C explizit eine Funktion an beliebiger Stelle ”verlassen” werden
kann, was durch das Schlüsselwort return erreicht wird.
➤ Prozeduren in C sind Funktionen ohne Rückgabewert. Der Ergebnistyp ist void.
➤ Die prozedurale/funktionale Abstraktion ist rekursiv. Einige Programmiersprachen erlauben
daher weitere (lokale) Funktionsdefinitionen innerhalb von Funktionen. C unterstützt diese
geschachtelten lokalen Funktionskontexte nicht!
Es gibt nur
1. globale Funktionen,
2. Modul-(Datei-) lokale Funktionen, die mit dem Schlüsselwort static definiert werden.
DEF sq2 == λ x •
LET sum == λ a,b • a+b IN sum (x,1)*sum(x,1)
Dr. Stefan Bosse •
Seite 119
Grundlagen der Informatik (B)
Programmiersprachen :: C :: Funktionen (IV)
➤ Funktionsaufruf:
Bei einem Funktionsaufruf werden die Parameter p der Funktion mit den Argumenten x initialisiert.
Pseudo−Notation
⇔
C−Notation
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
...
vartype v;
LET v == fun(x1,x2,...) IN
v = fun(x1,x2,...);
Beispiel:
LET a == sum(1,2) IN
int a;
a=sum(1,2);
➤ Parameterübergabemechanismen:
Man unterscheidet verschiedene Arten der Parameterübergabe, wobei C nur den Wertaufruf
unterstützt:
Wertaufruf
Der Parameter wird mit einem Wert als Argument beim Funktionsaufruf initialisiert.
➥ Eine Änderung des Parameters innerhalb der Funktion hat keinen äußeren Einfluß
(auf das Argument).
Seite 120
Dr. Stefan Bosse •
Grundlagen der Informatik (B)
Programmiersprachen :: C :: Funktionen (V)
➤ Parameterübergabemechanismen:
Ergebnisaufruf
Nach Beendigung der Funktion wird der (Ergebnis-)Wert an das Argument, eine Variable, zugewiesen.
➥ Änderung des Parameters hat äußeren Einfluß (auf das Argument)!
Referenzaufruf
Der Parameter wird mit einem Zeiger (einer Referenz) auf das Argument initialisiert.
➥ Argument und Funktionsparameter bezeichnen das gleiche Objekt, d.h. Änderungen
des Parameters haben sofort äußeren Einfluß!
➥ In C muß der Referenzaufruf explizit mit Zeigern realisiert werden.
{
int a;
int b;
a=5;
b=f_wert(a); ➥ a==5,b==7
f_ref(&b); ➥ b==5
}
int f_wert(int x)
{
return (x+2);
};
void f_ref(int *y)
{
*y=*y−2;
return;
};
Dr. Stefan Bosse •
Seite 121
Grundlagen der Informatik (B)
Programmiersprachen :: C :: Funktionen (VI)
➤ Rekursion:
Eine Funktion f heißt rekursiv, wenn während ihrer Ausführung f (mit veränderten Argumenten) nochmals aufgerufen wird.
Pseudo−Notation
⇔
C−Notation
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
DEF REC fac == λ n •
int fac(int n) {
IF n>1 THEN
int tmp;
n*fac(n−1)
if (n>1) {
ELSE 1
tmp=n*fac(n−1);
return (tmp);
} else
return 1;
};
➤ Eine rekursive Funktion muß immer ein Abbruchkriterium besitzen, welches ein relationaler
oder boolescher Ausdruck sein muß, der wenigstens einen Funktionsparameter enthält, der
sich im Funktionsrumpf ändert!
➥ Gefahr der Endlosrekursion wie bei Schleifen!
Seite 122
Dr. Stefan Bosse •
Grundlagen der Informatik (B)
Literatur
[PEP02]
P.Pepper
Funktionale Programmierung in Opal, ML, HASKELL und Gofer
Springer, 2002
[RRZN98]
Regionales Rechenzentrum für Niedersachsen/Universität Hannover
Die Programmiersprache C. Ein Nachschlagewerk
1998
Seite 123
Dr. Stefan Bosse •
Grundlagen der Informatik (B)
Herunterladen