Vorlesung 8 Flashcards
Zweck von Funktionen
- Häufig beinhalten Programme Teile, die mehrfach an verschiedenen Stellen
ausgeführt werden müssen. - Dieser Code wird in einer Funktion definiert, die an den entsprechenden
Stellen aufgerufen wird. - Vorteile:
- kürzere Programme
- einfache Wartung (Korrektur, Erweiterung, Anpassung an andere Systeme)
- Nachteil:
- Funktionsaufruf kosten minimal Rechenzeit (ist aber nur sehr selten relevant)
Definition eigener Funktionen
- Definition der Funktion
- Festlegung der Aufgaben durch Anweisungsfolge
- Der Programmcode wird nicht ausgeführt, sondern dem Compiler
bekannt gemacht - Syntax:
[Speicherklasse][Datentyp] Name ([Parameterliste und -definition])
Anweisungsblock
int quadrat(int x)
{
return x*x;
}
Funktionsaufruf
● Syntax: Name der Funktion ([Parameterliste und -definition])
● Sprung an die Definitionsstelle
● Abarbeitung der Anweisungen
● Fortsetzung des Programms mit dem ersten Befehl
nach dem Aufruf
y = quadrat(3);
Funktionen ohne Parameter / Rückgabewert
- Definition von Funktionen ohne Parameter
- Leere Parameterliste ()
- Definition von Funktionen ohne Rückgabewert
- Schlüsselwort void anstelle des Rückgabetyps
- Beispiel: Eine Funktion ohne Parameter und ohne Rückgabewert
void errorMessage()
{
printf(“An error occured.\n”);
}
Variablen in Funktionen
● Im Funktionsblock können Variablen definiert werden.
● Die Variablen sind lokale Variablen. Sie sind nur in der Funktion sichtbar,
andere Programmteile können nicht auf sie zugreifen.
● Der Speicher für lokale Variablen wird beim Funktionsaufruf angelegt und
nach Funktionsende gelöscht.
● Lokale Variablen werden nicht initialisiert.
void doSomething() {
int a, b;
…
}
int main() {
…
}
Parameter
include …
● Parameter sind Werte, die vom aufrufenden Programm an die Funktion
übergeben werden.
● Die Funktion führt die Anweisungsfolge mit diesen Werten durch.
● Parameter werden innerhalb der Funktion wie normale lokale
Variablen behandelt.
● Flexibles Konzept: für jeden Funktionsaufruf sind andere
Anfangswerte möglich.
● Funktionsparameter und lokale Variablen dürfen nicht den gleichen
Namen haben.
int compute(int a, int b) {
…
}
- Parameter sind im Funktionskopf durch Datentyp und Namen
eindeutig festgelegt. - Anzahl und Typen der Parameter von Funktionsaufruf und -definition müssen
übereinstimmen. - Unterscheidung zwischen
- Formalen Parametern (Definition der Funktion)
und - Aktuellen Parametern (Parameter, die beim
Funktionsaufruf verwendet werden) - Aktuelle und formale Parameter dürfen,
müssen aber nicht denselben
Namen haben.
int compute(int a, int b) {
…
}
int main() {
int c = 5, d = 6;
compute(c, d);
compute(10, 15);
}
double quadrat(double d)
{
…
}
double pot(double b, int e)
{
…
}
int main()
{
double d, z, q, p;
…
q = quadrat(d);
p = pot(z, 3);
…
}
Rückgabewert
● Mit dem Rückgabewert wird der berechnete Wert an die aufrufende Funktion
oder das aufrufende Programm übergeben.
● Sein Datentyp wird vor dem Namen in der Funktionsdefinition angegeben.
● Grunddatentypen und selbstdefinierte Datentypen* sind erlaubt
(int ist voreingestellt).
● Funktionen mit Rückgabewerten können im Programm wie ein einfacher
Ausdruck verwendet und behandelt werden:
y = 3 * quadrat(x + 2) + 5;
Die return-Anweisung
- Die return-Anweisung dient
- der sofortigen Beendigung einer Funktion und
- der Rückgabe eines Wertes (Ergebnis der Berechnungen in der Funktion) an
den aufrufenden Programmteil - Syntax: return Ausdruck;
- Der Datentyp des Rückgabewertes muss mit dem Datentyp der Funktion
kompatibel sein. - Gibt es keinen Rückgabetyp (void), wird kein Ausdruck angegeben:
12
return;
Sichtbarkeit von Variablen
- Variablen, die innerhalb von Blöcken deklariert werden:
- sie sind nur dort sichtbar (lokale Variablen)
- sie überdecken gleichnamige Variablen außerhalb des Blocks
- werden nicht automatisch initialisiert, d.h. sie enthalten „zufällige“ Werte
- manuelle Initialisierung bei der Deklaration: int var = 2;
- Variablen, die außerhalb aller Blöcke und Funktionen definiert werden
- sind überall sichtbar (globale Variablen)
- werden automatisch mit 0 initialisiert
Globale vs. lokale Variablen
- Globale Variablen
- sind überall sichtbar
- Speicher wird während der gesamten Laufzeit benötigt
- häufige Verwendung führt zu Fehlern durch Namensüberschneidungen
- verleiten zu unstrukturierten Programmen
- sollten soweit möglich vermieden werden
- Lokale Variablen
- sind im aktuellen Block und „Unterblöcken“ sichtbar.
- verhindern Namensüberschneidungen.
- fördern strukturierte Programmierung.
- Arbeitsspeicher wird nur für die Zeit belegt, in der der zugehörige Block / die zugehörige
Funktion aktiv ist.
Funktionen für Zeichen
● Funktionsdefinitionen in ctype.h
● Testfunktionen – liefert wahr (≠ 0), wenn übergebenes Zeichen zu einer
bestimmten Gruppe gehört, sonst falsch (0):
* int isalnum(int c): alphanumerische Zeichen
* int isdigit(int c): Dezimalziffer
* int isxdigit(int c): Hexadezimalziffer
* int isalpha(int c): Buchstaben (ohne Umlaute, etc.)
* int islower(int c): Kleinbuchstaben (ohne Umlaute, etc.)
* int isupper(int c): Großbuchstaben (ohne Umlaute, etc.)
* int isprint(int c): sichtbare Zeichen (inkl. Leerzeichen)
* int isgraph(int c): sichtbare Zeichen (ohne Leerzeichen)
* int ispunct(int c): sichtbare Zeichen (ohne Leerzeichen, Buchstaben, Ziffern)
* int isspace(int c): Leerzeichen, Seitenvorschub (\f), Zeilentrenner (\n),
Wagenrücklauf (\r), Tabulator (\t), Vertikaltabulator (\v)
* int iscntrl(int c): Steuerzeichen
* Umwandlungsfunktionen: wandelt übergebenes Zeichen in ein anderes
Zeichen um
* int toupper(int c): Kleinbuchstaben werden zu Großbuchstaben,
Rest unverändert
* int tolower(int c): Großbuchstaben werden zu Kleinbuchstaben,
Rest unverändert
Übergabemechanismen
int compute(int a, int b) {
…
}
result = compute(x, y);
- Übergabemechanismus in C ist immer call by value:
- Beim Funktionsaufruf werden Speicherplätze entsprechend der Definition der
formalen Parameter reserviert. - Die Kopien der aktuellen Parameter werden zu lokalen Variablen.
- Folge: Alles, was von nun an in der Funktion passiert, hat keine Auswirkung auf
die Variablen im aufrufenden Programmteil. - Möglichkeiten, Werte aus einer Funktion zurückzugeben:
1. Rückgabewert (return)
2. call by reference
(3. globale Variablen)
Call by reference
- Call by reference bedeutet:
- Funktion erhält Verweise auf Variablen (in C: Zeiger).
- Operationen in der Funktion arbeiten auf den Originaldaten.
- Heißt: Eine Funktion kann die originalen Variablen der aktuellen
Parameter ändern. - Call by reference wird in C mit Hilfe von Zeigern nachgebildet:
- Funktion erhält Adressen der Daten als Zeiger.
- Durch Dereferenzierung der Zeiger (Inhaltsoperator *) kann eine Funktion den
Inhalt von Parametern ändern.
int compute(int *a, int *b) {
…
}
result = compute(&x, &y);
Beispiel: call by value vs. call by reference
void inc_by_value(int i)
{
i++;
}
void inc_by_ref(int i)
{
(i)++;
}
int main()
{
int i = 0;
inc_by_value(i);
printf(“by value: %d\n”, i);
inc_by_ref(&i);
printf(“cbr: %d\n”, i);
return 0;
}
Statische Variablen in Funktionen
- Lebensdauer: während des gesamten Programms
- Anders formuliert: Statische Variablen in Funktionen „überleben“ das Ende
der Funktion. - Initialisierung: einmalig
- Sichtbarkeit: nur innerhalb der Funktion
- Anwendungsbereich: Wert soll zwischen Funktionsaufrufen erhalten bleiben,
aber zur Vermeidung von Namenskonflikten sowie zur Zugriffssicherung soll
keine globale Variable erzeugt werden. - Schlüsselwort static