Vorlesung 2 Flashcards
Warum gibt es Variablen und Datentypen?
● Variable (in der Informatik): logischer Speicherplatz, um Werte,
Zwischenergebnisse, Benutzereingaben etc. zu speichern.
● Anders formuliert: Eine Variable speichert Dinge, mit denen wir
arbeiten wollen.
● C ist streng typisierte Sprache, d.h. jede Variable muss von einem
bestimmten Datentyp sein und behält diesen, solange sie existiert.
● Variablen müssen vor erster Benutzung deklariert werden.
● Name [= Bezeichner] und Datentyp müssen festgelegt werden, bevor wir
mit der Variable arbeiten können.
Was sind die Elementaren Datentypen in C
- Elementare Datentypen
- char ein Byte oder Zeichen ‘A’ 65
- int ganze Zahl 1234 -1234
- float einfach genaue Gleitpunktzahl 3.45f
- double doppelt genaue Gleitpunktzahl 3.45
- Varianten
- short (int) geringerer Speicherbedarf / Wertebereich
- long (int) höherer Speicherbedarf / Wertebereich
- signed / unsigned Variable mit/ohne Vorzeichen (für int und char)
- long double besonders genaue Gleitpunktvariable
Nenne beispiele für Ganzzahlige Literale
- Dezimal
- 1234 ist vom Typ int
- 1234l und 1234L sind vom Typ long int
- 1234u und 1234U sind vom Typ unsigned int
- 1234ul und 1234UL sind vom Typ unsigned long int
- 123456789 ist vom Typ long int
● Oktal (beginnen mit 0) - 037 entspricht dezimal 31
● Hexadezimal (beginnen mit 0x oder 0X) - 0x1f und 0X1F entsprechen dezimal 31
- 0XFUL ist unsigned long mit Dezimalwert 15
Nenne beispiele für Gleitpunkt-Literale
● Mit Dezimalpunkt
* 1.234 ist double
* 1.234f und 1.234F sind float
* 1.234l und 1.234L sind long double
● Mit Exponenten
● Das e steht für „10 hoch“:
* 1234e-3 ist double und bedeutet 123410-3, also 1.234
* 1.234e2f ist float und bedeutet 1.234102, entspricht 123.4
double x1 = 1.234;
double x2 = 1234e-3;
float f = 12.5f;
Was sind Zeichen-Literale?
● Einzelne Zeichen in einfachen Anführungszeichen, z.B. ‘a’
* Entspricht numerischen Wert des Zeichens im Zeichensatz der Maschine
(Beachte: ‘7’ ≠ 7!) (i.d.R. ASCII)
● Zeichenketten in doppelten Anführungszeichen
* Beispiel: “Hello World”
● Ersatzdarstellungen für Sonderzeichen:
\a Klingelzeichen \ \ (Gegenschrägstrich)
\b Backspace \? ? (Fragezeichen)
\f Seitenvorschub ' ‘ (Anführungszeichen)
\n Zeilenumbruch " “ (Doppelanführungszeichen)
\r Wagenrücklauf \ooo Zeichen mit oktalem Wert
\t Tabulator \xhh Zeichen mit hexadezimalem Wert
\v vertikaler Tabulator
Sind Wertebereiche immer gleich?
- Die Wertebereiche von Variablen sind in C plattformabhängig
- Hinweis: Wertebereiche können aus limits.h und float.h
gelesen werden.
Nenne ein paar beispiele für Wichtige Operatoren auf Variablen
int l, m, n;
n = 15;
m = n + 3;
m = 5 * (n + 3) - 4;
a = 18;
b = 7;
c = a % b; // 4
Konstanten: wie geht die syntax und wann braucht man sie?
- Variablen können so definiert werden, dass man sie nach der ersten
Zuweisung nicht mehr ändern kann. - Umsetzung: Schlüsselwort const vor Variablendeklaration.
Wieviele generationen von programmiersprqchen gibt es und was zeichnet sie aus?
- Programmiersprachen lassen sich auf verschiedene Weisen klassifizieren.
- Einteilung nach Generationen:
- Einteilung erfolgt nach Abstraktionsniveau (je höher die Generation,
desto abstrakter). - Generation 1-2: Niedere Programmiersprachen (nah an der Hardware)
- Befehlssatz und Datentypen sind genau auf den verwendeten Rechner abgestimmt.
- Generation 3-5: Höhere Programmiersprachen (problemorientiert)
- Abstrakter, maschinenunabhängig. Werden entweder nach der Programmierung in
Maschinencode übersetzt oder während der Laufzeit interpretiert. - Einteilung nach Paradigmen:
- Ein Programmierparadigma bezeichnet das Model, mit dem ein Entwickler ein
Programm beschreibt.
- Generation: Maschinencode
- Binäre Befehle, z.B. für
- Daten aus dem Speicher in ein Prozessorregister holen (oder umgekehrt).
- Einfache Arithmetik mit den Inhalten der Register.
- Beispiel (Intel x86):
- 10110000 01100011 entspricht Hexadezimal B0 63
- Bedeutet: Lade in das AL Register den Operand (63)16
- Vor- und Nachteile
+ sehr schnell arbeitende Programme
– schwer zu lernen und zu lesen
– stark abhängig vom Prozessor
- Generation: Assemblercode
- Symbolische Befehle (Mnemonics) für die Binärcodes
- Bezeichner für Speicherstellen (inkl. Positionen im Programm)
- erleichtert die Programmierung enorm und hilft Fehler zu vermeiden
- Beispiel (Assemblercode für den Binärcode aus vorherigem Beispiel)
- mv al, 63h (vorher: 10110000 01100011)
- Mittels eines Assemblers werden symbolische Befehle in Maschinencode übersetzt.
- Einsatzgebiet: hochgradig optimierte Routinen, systemnahe Programmierung,
Mikrocontroller, für die keine Hochsprache verfügbar ist. - Vor- und Nachteile
+ sehr schnell arbeitende Programme
– viel Zeit zur Programmierung notwendig anstatt zur eigentlichen Problemlösung
– abhängig vom Prozessor
- Generation: Höhere Programmiersprachen
- Höheres Abstraktionsniveau, damit näher am zu lösenden Problem
- Verwendung von Variablen
- Komplexe Datentypen
- Blockweiser Aufbau mit klaren Kontrollstrukturen (kein wildes Hin- und Herspringen)
- Prozeduren und Funktionen erlauben einfache Mehrfachverwendung von Code-Teilen
- Verschiedene Paradigmen (z.B. prozedural, objektorientiert)
- Beispiele: C, C++, Java, Python, Fortran, Algol, Pascal
- Vorteile
+ leicht erlernbar und lesbar
+ schnell
+ geringe Abhängigkeit von der Hardware
– teilweise Unterschiede zwischen
Betriebssystemen, Rechnertypen, Übersetzern
- Generation
- Das „Was“ steht im Vordergrund, nicht das „Wie“.
- Domänenspezifische Sprachen, d.h. für bestimmte Einsatzgebiete
- Beispiele
- SQL (Structured Query Language): Sprache zur Datenbankabfrage, es wird beschrieben, welche
Daten benötigt werden, aber nicht wie sie gefunden werden sollen - Deskriptive Sprachen: HTML beschreibt, wie eine Web-Seite aussehen soll, nicht aber wie der
Browser sie zeichnen soll - Matlab, Mathematica: Sprachen für mathematische Berechnungen
- Skriptsprachen, die andere Programme steuern (z.B. VBA)
- Werkzeuge zur graphischen Programmierung (GUI-Design, Ablaufpläne)
- Vor- und Nachteile
+ problemnah
+ keine Definition von Einzelschritten notwendig
– wenig flexibel
- Generation
- Keine Lösung des Problems wird angegeben, sondern Beschreibung von
Rand- und Zwangsbedingungen (Constraints) - Einsatzgebiete: künstliche Intelligenz, Forschung
- Beispiele
- Prolog: basiert auf Prädikatenlogik, bei der Programmierung werden Fakten und Regeln
festgelegt, anhand derer das System später Fragen beantwortet - Lisp: basiert auf dem Lambda-Kalkül, alles wird als Funktion definiert, alle Objekte sind
Listen, die nach bestimmten Regeln miteinander verknüpft werden - Vor- und Nachteile
+ allgemein
+ maschinenunabhängig
+ kurze Programme für komplexe Probleme möglich
– langsam
Was versteht man unter Programmierparadigmen?
Welche paradigmen sind üblich?
- Ein Programmierparadigma ist ein fundamentaler Programmierstil.
- Er beschreibt das Modell, mit dem ein Programmierer ein Programm auffasst.
- Programmiersprachen folgen einem oder mehreren Paradigmen.
- Übliche Paradigmen:
- Imperativ
- Deklarativ
- Funktional
- Logisch
- Objektorientiert
Programmierparadigmen: Imperativ vs. deklarativ
Was sind die unterschiede der beiden programmierparadigmen?
Imperativ
Programm besteht aus Anweisungen die
beschreiben, wie das Programm seine
Ergebnisse erzeugt
Deklarativ
Programm besteht aus Bedingungen (dem
Was), welche die Ausgabe des Programms
erfüllen muss
Paradigma: Objektorientiert,
Wie funktioniert objektorientierte sprache?
Objektorientiert: Daten und die darauf arbeitenden Routinen werden zu
Einheiten („Objekten“) zusammengefasst. Ein Computerprogramm ist eine
Menge miteinander interagierender Objekte.
Wie funktioniert das programmierparadigma: Funktional?
Das Programm wird als funktionaler Ausdruck aufgefasst. Das selbstständige
Anwenden von Funktionsersetzung und Auswertung seitens des
Interpreters / Compilers löst dann die Aufgabenstellung.
Wie funktioniert das programmierparadigma: Logisch?
Logisch: Die Aufgabenstellung und ihre Prämissen werden als logische
Aussagen (Regeln) formuliert. Der Interpreter versucht, die gewünschte
Lösungsaussage herzuleiten / zu beweisen
Wie kommt man vom Quelltext zum ausführbaren Programm?
- Ein Entwickler schreibt ein Programm als reinen Text, dem Quelltext, in einer
bestimmten Programmiersprache. - Am Ende werden alle Programme in Maschinecode umgesetzt
und ausgeführt. - Dazu gibt es zwei Möglichkeiten:
- Der Quelltext wird interpretiert.
- Der Quelltext wird in Maschinensprache übersetzt.
Was sind die unterschiede zwischen Interpreter und Compiler?
- Ein Interpreter ist ein Programm, das das Programm des Entwicklers einliest,
interpretiert und schrittweise ausführt. - Das Programm wird also nicht in Maschinensprache übersetzt.
- Beispiele: Python, PHP, JavaScript, BASIC
- Vor- und Nachteile:
+ Plattform-unabhängig (Hardware, Betriebssystem)
+ Programmiersprachen weniger strikt und sehr flexibel
– Benötigt Installation eines Interpreter-Programms
– Langsame Ausführung, da Programm interpretiert werden muss
– Kein direkter Zugriff auf Hardware möglich
– Keine Code-Optimierung möglich - Ein Compiler übersetzt das Programm in Maschinensprache.
- Das übersetzte Programm kann direkt gestartet werden.
- Beispiel: C
- Vor- und Nachteile:
+ Hocheffizienter, schneller, direkt ausführbarer Code
+ Direkte Nutzung von Hardware-Eigenheiten möglich
+ Code-Optimierung
– Programm nur auf gewählten Zielplattformen lauffähig
Was sind die funktionen von Compiler und Linker?
- Compiler
- (deutsch auch Übersetzer, Kompilierer)
- Aufgabe: Übersetzung des einzelnen Module (Teile) eines Quelltextes in
Maschinencode - Ergebnis: Kompilierte Module / Objektdateien
- Analysephase: Überprüfung auf Korrektheit des Eingabeprogramms
- Synthesephase: Konstruktion des Programms in der Maschinensprache
- Linker
- Baut alle Module zu einem ausführbaren Programm zusammen
- Bindet dabei externe Bibliotheken und Funktionen ein
Was sind die Arbeitsschritte eines Compilers?
- Lexikalische Analyse
- Zerlegung in Folge von Symbolen
(Bezeichner, Literale, Schlüsselwörter, …) - Überlesen bedeutungsloser Zeichen
- Lexikalische Korrektheit
- Symboltabelle
- Speichert die verwendeten Bezeichner
(Variablennamen, Funktionsnamen, …)
und sorgt für korrekte Zuordnung - Syntaktische Analyse
- Prüfung auf syntaktische Korrektheit
- Zusammenfügen der Symbolfolgen der
lexikalischen Analyse zu syntaktische Einheiten
(Deklarationen, Anweisungen, Ausdrücke, …) - Semantische Analyse
- Kontextabhängige Prüfung (z.B. sind
aufgerufene Funktionen definiert,
benutzte Variablen deklariert) - Zwischencodeerzeugung
- Erzeugung der ersten Version des
Ausgabeprogramms - Codeoptimierung (optional)
- Der Maschinencode kann nach
verschiedenen Kriterien optimiert werden
(Laufzeit, Speicherbedarf, …).
Nenne alle 5 Compiler-Typen
- Prä-Compiler: eine Vorstufe zum eigentlichen Compiler, z.B. um andere
Quelltextdateien einzubinden, automatisches Ersetzen vor der Übersetzung
durchzuführen - Cross-Compiler: Das ausgegebene Maschinensprachen-Programm ist für
eine andere Plattform bestimmt, als die Plattform, auf der entwickelt wird
(wird z.B. eingesetzt bei eingebetteten Systeme) - Just-In-Time Compiler: Der Code wird erst während der Ausführung des
Programms übersetzt (z.B. integriert in einen Interpreter) - Nachgeschalteter Assembler: Ist die Ausgabe des Compilers Assembler und
nicht Maschinensprache, so muss ein Assemblierer nachgeschaltet werden - Transpiler (source-to-source compiler): Programm wird in andere
Programmiersprache übersetzt (z.B. TypeScript nach JavaScript).
Was macht Der Linker?
- Große Programme werden in verschiedene Module
aufgeteilt, die… - … möglicherweise von unterschiedlichen Personen
bearbeitet werden - … evtl. sogar unterschiedliche Programmiersprachen
einsetzten - Jedes Module wird mit einem Compiler in die
Maschinensprache übersetzt, aber noch nicht als
ausführbare Datei, sondern als Objektdatei. - Die unterschiedlichen Objektdateien werden von
dem Linker zu einer Datei zusammengefügt. - Dabei ist es z.B. auch möglich, dass ein Modul
Funktionen eines anderen nutzt.