20.07.2013 Aufrufe

Einführung in die Programmierung - Hochschule Niederrhein

Einführung in die Programmierung - Hochschule Niederrhein

Einführung in die Programmierung - Hochschule Niederrhein

MEHR ANZEIGEN
WENIGER ANZEIGEN

Sie wollen auch ein ePaper? Erhöhen Sie die Reichweite Ihrer Titel.

YUMPU macht aus Druck-PDFs automatisch weboptimierte ePaper, die Google liebt.

ma<strong>in</strong><br />

ma<strong>in</strong><br />

<strong>E<strong>in</strong>führung</strong> <strong>in</strong> <strong>die</strong> <strong>Programmierung</strong><br />

Def<strong>in</strong>ition nach ANSI C:<br />

Bachelor of Science<br />

Prof. Dr. Rethmann<br />

Fachbereich Elektrotechnik und Informatik<br />

<strong>Hochschule</strong> Niederrhe<strong>in</strong><br />

WS 2009/10<br />

<strong>in</strong>t ma<strong>in</strong>(<strong>in</strong>t argc, char *argv[]) {<br />

....<br />

return 0;<br />

}<br />

Zeichenfolgen als Parameter übergeben:<br />

argc (argument count): Anzahl der beim Aufruf angegebenen<br />

Zeichenfolgen <strong>in</strong>kl. Programmname<br />

argv (argument vector): Vektor von Zeigern auf <strong>die</strong><br />

angegebenen Zeichenfolgen<br />

argv[0] = Programmname<br />

Rückgabewert 0: erfolgreich ausgeführtes Programm<br />

<strong>E<strong>in</strong>führung</strong> <strong>in</strong> <strong>die</strong> <strong>Programmierung</strong> <strong>die</strong> ma<strong>in</strong>-Funktion 3 / 41<br />

üblich: Str<strong>in</strong>g-Array zur Abfrage von Umgebungsvariablen.<br />

#<strong>in</strong>clude <br />

void ma<strong>in</strong>(<strong>in</strong>t argc, char *argv[], char *env[]) {<br />

<strong>in</strong>t i;<br />

}<br />

for (i = 0; env[i] != NULL; i++)<br />

pr<strong>in</strong>tf("Variable %d = %s\n", i, env[i]);<br />

Erzeugt beim Aufruf unter L<strong>in</strong>ux bspw. <strong>die</strong> Ausgabe:<br />

Variable 0 = TERM=xterm<br />

Variable 1 = SHELL=/b<strong>in</strong>/bash<br />

Variable 2 = PAGER=/usr/b<strong>in</strong>/less<br />

Variable 3 = LANG=de_DE.UTF-8<br />

...<br />

<strong>E<strong>in</strong>führung</strong> <strong>in</strong> <strong>die</strong> <strong>Programmierung</strong> <strong>die</strong> ma<strong>in</strong>-Funktion 5 / 41<br />

Übersicht<br />

<strong>die</strong> ma<strong>in</strong>-Funktion<br />

Speicherverwaltung<br />

Rekursive Funktionen<br />

Gültigkeitsbereiche<br />

<strong>E<strong>in</strong>führung</strong> <strong>in</strong> <strong>die</strong> <strong>Programmierung</strong> Speicherverwaltung 7 / 41<br />

Übersicht<br />

ma<strong>in</strong><br />

<strong>die</strong> ma<strong>in</strong>-Funktion<br />

Speicherverwaltung<br />

Rekursive Funktionen<br />

Gültigkeitsbereiche<br />

<strong>E<strong>in</strong>führung</strong> <strong>in</strong> <strong>die</strong> <strong>Programmierung</strong> <strong>die</strong> ma<strong>in</strong>-Funktion 2 / 41<br />

#<strong>in</strong>clude <br />

void ma<strong>in</strong>(<strong>in</strong>t argc, char *argv[]) {<br />

<strong>in</strong>t i;<br />

}<br />

ma<strong>in</strong><br />

for (i = 0; i < argc; i++)<br />

pr<strong>in</strong>tf("Parameter %d = %s\n", i, argv[i]);<br />

Wird das Programm als arg.c gespeichert und mit arg e<strong>in</strong>s 2<br />

drei ausgeführt, so wird folgende Ausgabe erzeugt:<br />

Parameter 0 = arg<br />

Parameter 1 = e<strong>in</strong>s<br />

Parameter 2 = 2<br />

Parameter 3 = drei<br />

<strong>E<strong>in</strong>führung</strong> <strong>in</strong> <strong>die</strong> <strong>Programmierung</strong> <strong>die</strong> ma<strong>in</strong>-Funktion 4 / 41<br />

Umwandeln der Programmparameter: sscanf(char *s, ...)<br />

äquivalent zu scanf, aber E<strong>in</strong>gabezeichen stammen aus der<br />

Zeichenkette s.<br />

Beispiel:<br />

Rückgabewert: Anzahl der umgewandelten E<strong>in</strong>gaben.<br />

<strong>in</strong>t i, n, p;<br />

for (i = 0; i < argc; errno = 0, i++) {<br />

p = sscanf(argv[i], "%d", &n);<br />

if (p == 0)<br />

pr<strong>in</strong>tf("failed to convert %s\n", argv[i]);<br />

else if (errno == ERANGE)<br />

pr<strong>in</strong>tf("%s is out of range\n", argv[i]);<br />

else pr<strong>in</strong>tf("%d: value %d\n", i, n);<br />

}<br />

<strong>E<strong>in</strong>führung</strong> <strong>in</strong> <strong>die</strong> <strong>Programmierung</strong> <strong>die</strong> ma<strong>in</strong>-Funktion 6 / 41<br />

Speicherverwaltung<br />

Der von e<strong>in</strong>em C-Programm während se<strong>in</strong>er Ausführung belegte<br />

Speicher ist <strong>in</strong> vier Bereiche aufgeteilt:<br />

Code-Segment: enthält das übersetzte Programm, also <strong>die</strong><br />

auszuführenden Masch<strong>in</strong>enbefehle.<br />

Statische Daten: während des gesamten Lebenszyklus<br />

verfügbare Daten wie globale Variablen oder statische, lokale<br />

Variablen.<br />

Heap: dynamisch allozierter Speicher (malloc)<br />

Stack: Informationen über Funktionsaufrufe<br />

<strong>E<strong>in</strong>führung</strong> <strong>in</strong> <strong>die</strong> <strong>Programmierung</strong> Speicherverwaltung 8 / 41


Speicherverwaltung<br />

Für <strong>die</strong> lokalen Variablen und Argumente e<strong>in</strong>er Funktion wird erst<br />

beim Aufruf der Funktion Speicherplatz reserviert.<br />

Nach Beenden der Funktion wird der Speicherplatz wieder<br />

freigegeben.<br />

ma<strong>in</strong><br />

SP<br />

fkt1<br />

ma<strong>in</strong><br />

SP<br />

fkt2<br />

fkt1<br />

ma<strong>in</strong><br />

SP<br />

fkt1<br />

ma<strong>in</strong><br />

E<strong>in</strong> CPU-Register (SP: Stack Po<strong>in</strong>ter) enthält <strong>die</strong> Adresse des<br />

nächsten freien Speicherplatzes.<br />

<strong>E<strong>in</strong>führung</strong> <strong>in</strong> <strong>die</strong> <strong>Programmierung</strong> Speicherverwaltung 9 / 41<br />

Speicherverwaltung<br />

Vorsicht: Zeiger auf lokale Variablen als Rückgabewert e<strong>in</strong>er<br />

Funktion liefern ke<strong>in</strong>en def<strong>in</strong>ierten Wert!<br />

char* <strong>in</strong>tToStr<strong>in</strong>g(<strong>in</strong>t a) {<br />

char s[10];<br />

<strong>in</strong>t i, t;<br />

}<br />

for (t = 1; t < a; t *= 10)<br />

;<br />

for (t /= 10, i = 0; t > 0; t/= 10, i++)<br />

s[i] = (a / t) % 10 + ’0’;<br />

s[i] = ’\0’;<br />

return s;<br />

<strong>E<strong>in</strong>führung</strong> <strong>in</strong> <strong>die</strong> <strong>Programmierung</strong> Speicherverwaltung 11 / 41<br />

Übersicht<br />

<strong>die</strong> ma<strong>in</strong>-Funktion<br />

Speicherverwaltung<br />

Rekursive Funktionen<br />

Gültigkeitsbereiche<br />

<strong>E<strong>in</strong>führung</strong> <strong>in</strong> <strong>die</strong> <strong>Programmierung</strong> Rekursive Funktionen 13 / 41<br />

Fakultät – C-Code<br />

#<strong>in</strong>clude <br />

<strong>in</strong>t fact(<strong>in</strong>t n) {<br />

if (n max)<br />

max = a[i];<br />

}<br />

res[0] = max;<br />

res[1] = m<strong>in</strong>;<br />

return res;<br />

<strong>E<strong>in</strong>führung</strong> <strong>in</strong> <strong>die</strong> <strong>Programmierung</strong> Speicherverwaltung 12 / 41<br />

Rekursive Funktionen<br />

Rekursion <strong>in</strong> der Mathematik:<br />

B<strong>in</strong>omialkoeffizienten:<br />

<br />

n n − 1 n − 1<br />

= + mit<br />

k k − 1 k<br />

Fibonacci-Zahlen:<br />

<br />

n<br />

= 1 und<br />

n<br />

Fn = Fn−1 + Fn−2 mit F0 = 0 und F1 = 1<br />

<br />

n<br />

= 1<br />

0<br />

Determ<strong>in</strong>ante: Die Adjunkte Aik ist <strong>die</strong> Determ<strong>in</strong>ante<br />

(n − 1)ter Ordnung, <strong>die</strong> durch Streichen der i-ten Zeile und<br />

k-ten Spalte, multipliziert mit (−1) i+k entsteht.<br />

Entwickeln nach der i-ten Zeile:<br />

n<br />

D(aij) =<br />

k=1<br />

aikAik<br />

<strong>E<strong>in</strong>führung</strong> <strong>in</strong> <strong>die</strong> <strong>Programmierung</strong> Rekursive Funktionen 14 / 41<br />

Fakultät – Programmablauf<br />

Aufrufe Rückgabe<br />

fact(4)<br />

= 4 * fact(3)<br />

fact(3)<br />

= 3 * fact(2)<br />

= 3 * 2 = 6<br />

fact(2)<br />

= 2 * fact(1) = 2 * 1 = 2<br />

fact(1) = 1<br />

= 4 * 6 = 24<br />

<strong>E<strong>in</strong>führung</strong> <strong>in</strong> <strong>die</strong> <strong>Programmierung</strong> Rekursive Funktionen 16 / 41


B<strong>in</strong>omialkoeffizienten – C-Code<br />

#<strong>in</strong>clude <br />

<strong>in</strong>t b<strong>in</strong>(<strong>in</strong>t n, <strong>in</strong>t k) {<br />

if (n < k || k < 0)<br />

return -1;<br />

}<br />

if (k == 0 || k == n)<br />

return 1;<br />

return b<strong>in</strong>(n-1, k-1) + b<strong>in</strong>(n-1, k);<br />

void ma<strong>in</strong>() {<br />

pr<strong>in</strong>tf("b<strong>in</strong>(%d,%d) = %d\n", 7, 3, b<strong>in</strong>(7, 3));<br />

}<br />

<strong>E<strong>in</strong>führung</strong> <strong>in</strong> <strong>die</strong> <strong>Programmierung</strong> Rekursive Funktionen 17 / 41<br />

B<strong>in</strong>omialkoeffizienten – Speicherverwaltung<br />

n = 4<br />

k = 1<br />

b<strong>in</strong> = ?<br />

n = 4<br />

k = 1<br />

b<strong>in</strong> = ?<br />

n = 3<br />

k = 0<br />

b<strong>in</strong> = 1<br />

n = 4 n = 4<br />

k = 1 k = 1<br />

b<strong>in</strong> = 1<br />

b<strong>in</strong> = 1<br />

n = 3<br />

k = 1<br />

b<strong>in</strong> = ?<br />

n = 4<br />

k = 1<br />

b<strong>in</strong> = 1<br />

n = 3<br />

k = 1<br />

b<strong>in</strong> = ?<br />

n = 2<br />

k = 0<br />

b<strong>in</strong> = 1<br />

n = 4<br />

k = 1<br />

b<strong>in</strong> = 1<br />

n = 3<br />

k = 1<br />

b<strong>in</strong> = 1<br />

n = 4 n = 4<br />

k = 1<br />

b<strong>in</strong> = 1<br />

n = 3<br />

k = 1<br />

b<strong>in</strong> = 1<br />

n = 2<br />

k = 1<br />

b<strong>in</strong> = ?<br />

k = 1<br />

b<strong>in</strong> = 1<br />

n = 3<br />

k = 1<br />

b<strong>in</strong> = 1<br />

n = 2<br />

k = 1<br />

b<strong>in</strong> = ?<br />

n = 1<br />

k = 0<br />

b<strong>in</strong> = 1<br />

n = 4 n = 4<br />

k = 1<br />

b<strong>in</strong> = 1<br />

n = 3<br />

k = 1<br />

b<strong>in</strong> = 1<br />

n = 2<br />

k = 1<br />

b<strong>in</strong> = 1<br />

k = 1<br />

b<strong>in</strong> = 1<br />

n = 3<br />

k = 1<br />

b<strong>in</strong> = 1<br />

n = 2<br />

k = 1<br />

b<strong>in</strong> = 1<br />

n = 1<br />

k = 1<br />

b<strong>in</strong> = 1<br />

n = 4 n = 4<br />

k = 1<br />

b<strong>in</strong> = 1<br />

n = 3<br />

k = 1<br />

b<strong>in</strong> = 1<br />

n = 2<br />

k = 1<br />

b<strong>in</strong> = 2<br />

k = 1<br />

b<strong>in</strong> = 1<br />

n = 3<br />

k = 1<br />

b<strong>in</strong> = 3<br />

b<strong>in</strong> = 4<br />

<strong>E<strong>in</strong>führung</strong> <strong>in</strong> <strong>die</strong> <strong>Programmierung</strong> Rekursive Funktionen 19 / 41<br />

Umwandeln <strong>in</strong> B<strong>in</strong>ärdarstellung<br />

C-Code:<br />

#<strong>in</strong>clude <br />

void <strong>in</strong>tToB<strong>in</strong>(<strong>in</strong>t n) {<br />

if (n < 2) {<br />

pr<strong>in</strong>tf("%1d", n);<br />

return;<br />

}<br />

}<br />

<strong>in</strong>tToB<strong>in</strong>(n / 2);<br />

pr<strong>in</strong>tf("%1d", n % 2);<br />

void ma<strong>in</strong>(void) {<br />

<strong>in</strong>tToB<strong>in</strong>(11);<br />

}<br />

Ablauf:<br />

<strong>in</strong>tToB<strong>in</strong>(n)<br />

11<br />

11<br />

5<br />

5<br />

2<br />

2<br />

1<br />

n = 4<br />

k = 1<br />

Ausgabe<br />

<strong>E<strong>in</strong>führung</strong> <strong>in</strong> <strong>die</strong> <strong>Programmierung</strong> Rekursive Funktionen 21 / 41<br />

Rekursion und Mathematik<br />

Beispiel:<br />

n<br />

i =<br />

i=1<br />

n · (n + 1)<br />

2<br />

Induktionsanfang für n = 1: −→ Rekursionsende<br />

1<br />

i = 1 ! =<br />

i=1<br />

1 · 2<br />

2<br />

= 1<br />

Induktionsschluss n ❀ n + 1: −→ rekursiver Aufruf<br />

n+1<br />

i =<br />

i=1<br />

n<br />

i + (n + 1)<br />

i=1<br />

I.A. n · (n + 1)<br />

= + (n + 1)<br />

2<br />

= (n + 1) · (n + 2)<br />

2<br />

<strong>E<strong>in</strong>führung</strong> <strong>in</strong> <strong>die</strong> <strong>Programmierung</strong> Rekursive Funktionen 23 / 41<br />

1<br />

0<br />

1<br />

1<br />

B<strong>in</strong>omialkoeffizienten – Programmablauf<br />

(4, 1)<br />

+<br />

(3, 0)<br />

(2, 0)<br />

(1, 0)<br />

(3, 1)<br />

+<br />

(2, 1)<br />

+<br />

(1, 1)<br />

(5, 2)<br />

+<br />

(1, 0)<br />

(3, 1)<br />

+<br />

(2, 0) (2, 1)<br />

+<br />

(1, 1)<br />

(4, 2)<br />

+<br />

(3, 2)<br />

+<br />

(2, 1)<br />

+<br />

(1, 0)<br />

(2, 2)<br />

(1, 1)<br />

<strong>E<strong>in</strong>führung</strong> <strong>in</strong> <strong>die</strong> <strong>Programmierung</strong> Rekursive Funktionen 18 / 41<br />

Quersumme<br />

#<strong>in</strong>clude <br />

<strong>in</strong>t qsum(unsigned <strong>in</strong>t zahl) {<br />

<strong>in</strong>t ziffer;<br />

}<br />

if (zahl < 10)<br />

return zahl;<br />

ziffer = zahl % 10;<br />

return ziffer + qsum(zahl / 10);<br />

void ma<strong>in</strong>(void) {<br />

unsigned <strong>in</strong>t i;<br />

}<br />

for (i = 731; i < 750; i++)<br />

pr<strong>in</strong>tf("Quersumme(%d)= %d\n", i, qsum(i));<br />

<strong>E<strong>in</strong>führung</strong> <strong>in</strong> <strong>die</strong> <strong>Programmierung</strong> Rekursive Funktionen 20 / 41<br />

Rekursion und Mathematik<br />

Rekursion kennen wir auch an anderer Stelle <strong>in</strong> der Mathematik:<br />

Beweis durch vollständige Induktion<br />

Beispiel:<br />

#<strong>in</strong>clude <br />

<strong>in</strong>t sum(unsigned <strong>in</strong>t n) {<br />

if (n == 1)<br />

return n;<br />

return n + sum(n-1);<br />

}<br />

void ma<strong>in</strong>(void) {<br />

pr<strong>in</strong>tf("Summe 1+...+10 = %d\n", sum(10));<br />

}<br />

<strong>E<strong>in</strong>führung</strong> <strong>in</strong> <strong>die</strong> <strong>Programmierung</strong> Rekursive Funktionen 22 / 41<br />

Übersicht<br />

<strong>die</strong> ma<strong>in</strong>-Funktion<br />

Speicherverwaltung<br />

Rekursive Funktionen<br />

Gültigkeitsbereiche<br />

<strong>E<strong>in</strong>führung</strong> <strong>in</strong> <strong>die</strong> <strong>Programmierung</strong> Gültigkeitsbereiche 24 / 41


Gültigkeitsbereich von Bezeichnern<br />

Gültigkeitsbereich (scope): Der Teil des Programms, wo e<strong>in</strong><br />

Bezeichner benutzt werden kann.<br />

Die Bedeutung e<strong>in</strong>er Deklaration ist abhängig von deren Stelle im<br />

C-Code. Mögliche Stellen für Deklarationen:<br />

außerhalb von Funktionen: globale Variablen<br />

im Funktionskopf: formale Parameter e<strong>in</strong>er Funktion<br />

<strong>in</strong>nerhalb e<strong>in</strong>es Blocks: lokale Variablen<br />

Funktionen können nur außerhalb von Funktionen deklariert<br />

werden.<br />

<strong>E<strong>in</strong>führung</strong> <strong>in</strong> <strong>die</strong> <strong>Programmierung</strong> Gültigkeitsbereiche 25 / 41<br />

Gültigkeitsbereich von Bezeichnern<br />

typedef struct node {<br />

struct node *pred, *succ;<br />

<strong>in</strong>t value;<br />

} node_t;<br />

typedef struct list {<br />

node_t *first, *last;<br />

<strong>in</strong>t size;<br />

} list_t;<br />

list_t * create(void);<br />

void enqueue(list_t *l, <strong>in</strong>t val);<br />

<strong>in</strong>t dequeue(list_t *l);<br />

char isEmpty(list_t *l);<br />

liste.h<br />

<strong>E<strong>in</strong>führung</strong> <strong>in</strong> <strong>die</strong> <strong>Programmierung</strong> Gültigkeitsbereiche 27 / 41<br />

Gültigkeitsbereich von Bezeichnern<br />

void enqueue(list_t *l, <strong>in</strong>t val) {<br />

node_t *neu;<br />

node_t *p = l->last->pred;<br />

}<br />

neu = (node_t *) malloc(sizeof(node_t));<br />

neu->value = val;<br />

neu->succ = l->last;<br />

neu->pred = p;<br />

p->succ = neu;<br />

l->last->pred = neu;<br />

l->size += 1;<br />

char isEmpty(list_t *l) {<br />

return l->size == 0;<br />

}<br />

<strong>E<strong>in</strong>führung</strong> <strong>in</strong> <strong>die</strong> <strong>Programmierung</strong> Gültigkeitsbereiche 29 / 41<br />

Gültigkeitsbereich von Bezeichnern<br />

#<strong>in</strong>clude <br />

#<strong>in</strong>clude "liste.h"<br />

<strong>in</strong>t ma<strong>in</strong>(void) {<br />

<strong>in</strong>t i;<br />

list_t *list;<br />

}<br />

list = create();<br />

for (i = 3; i < 20; i++)<br />

enqueue(list, i);<br />

while (!isEmpty(list))<br />

pr<strong>in</strong>tf("%d\n", dequeue(list));<br />

return 0;<br />

haupt.c<br />

<strong>E<strong>in</strong>führung</strong> <strong>in</strong> <strong>die</strong> <strong>Programmierung</strong> Gültigkeitsbereiche 31 / 41<br />

Gültigkeitsbereich von Bezeichnern<br />

Module: C-Quellcode auf mehrere Dateien aufteilen:<br />

e<strong>in</strong>e Datei enthält Vere<strong>in</strong>barungen und/oder Funktionen<br />

nur e<strong>in</strong>e Datei darf <strong>die</strong> Funktion ma<strong>in</strong> enthalten<br />

Beispiel: Liste<br />

liste.h: enthält <strong>die</strong> Datenstruktur und <strong>die</strong> Deklaration aller<br />

Zugriffsmethoden<br />

liste.c: Implementierung aller Zugriffsmethoden<br />

haupt.c: Programm verwendet <strong>die</strong> Liste, enthält ma<strong>in</strong><br />

⇒ gleichzeitiges Arbeiten am Source-Code möglich<br />

<strong>E<strong>in</strong>führung</strong> <strong>in</strong> <strong>die</strong> <strong>Programmierung</strong> Gültigkeitsbereiche 26 / 41<br />

Gültigkeitsbereich von Bezeichnern<br />

#<strong>in</strong>clude <br />

#<strong>in</strong>clude "liste.h"<br />

list_t * create(void) {<br />

list_t *l;<br />

}<br />

liste.c<br />

l = (list_t *) malloc(sizeof(list_t));<br />

l->first = (node_t *) malloc(sizeof(node_t));<br />

l->last = (node_t *) malloc(sizeof(node_t));<br />

l->first->succ = l->last;<br />

l->first->pred = NULL;<br />

l->last->succ = NULL;<br />

l->last->pred = l->first;<br />

l->size = 0;<br />

return l;<br />

<strong>E<strong>in</strong>führung</strong> <strong>in</strong> <strong>die</strong> <strong>Programmierung</strong> Gültigkeitsbereiche 28 / 41<br />

Gültigkeitsbereich von Bezeichnern<br />

<strong>in</strong>t dequeue(list_t *l) {<br />

<strong>in</strong>t res = -1;<br />

node_t *f;<br />

}<br />

if (isEmpty(l))<br />

return res;<br />

f = l->first->succ;<br />

l->first->succ = f->succ;<br />

f->succ->pred = l->first;<br />

res = f->value;<br />

l->size -= 1;<br />

free(f);<br />

return res;<br />

<strong>E<strong>in</strong>führung</strong> <strong>in</strong> <strong>die</strong> <strong>Programmierung</strong> Gültigkeitsbereiche 30 / 41<br />

Gültigkeitsbereich von Bezeichnern<br />

liste.c<br />

liste.obj<br />

liste.h<br />

#<strong>in</strong>clude #<strong>in</strong>clude<br />

Prä−Compiler<br />

Compiler<br />

L<strong>in</strong>ker<br />

haupt.exe<br />

haupt.c<br />

haupt.obj<br />

<strong>E<strong>in</strong>führung</strong> <strong>in</strong> <strong>die</strong> <strong>Programmierung</strong> Gültigkeitsbereiche 32 / 41


Gültigkeitsbereich von Bezeichnern<br />

Es gibt vier mögliche Gültigkeitsbereiche:<br />

der Compiler kennt nur, was er bereits gelesen hat, aber ke<strong>in</strong>e<br />

anderen Dateien → globale Variablen und alle Funktionen<br />

gelten vom Deklarationspunkt bis zum Ende der Datei<br />

formale Funktionsparameter gelten vom Deklarationspunkt bis<br />

zum Ende der Funktion bzw. des Prototypen<br />

lokale Variablen am Beg<strong>in</strong>n e<strong>in</strong>es Blocks gelten bis zum Ende<br />

des Blocks<br />

Anweisungsmarken gelten <strong>in</strong>nerhalb der Funktion, <strong>in</strong> der <strong>die</strong><br />

Deklaration erfolgt<br />

<strong>E<strong>in</strong>führung</strong> <strong>in</strong> <strong>die</strong> <strong>Programmierung</strong> Gültigkeitsbereiche 33 / 41<br />

Lebensdauer von Objekten<br />

Wie lange bleibt e<strong>in</strong> Objekt im Speicher und kann über se<strong>in</strong>en<br />

Bezeichner angesprochen werden?<br />

statische Lebensdauer: Objekte s<strong>in</strong>d stets verfügbar<br />

Funktionen<br />

globale Variablen<br />

statische Variablen<br />

automatische Lebensdauer: Objekte, <strong>die</strong> zu Beg<strong>in</strong>n e<strong>in</strong>es<br />

Blocks angelegt werden, s<strong>in</strong>d nach dem Verlassen des Blocks<br />

nicht mehr verfügbar, sofern nicht anders def<strong>in</strong>iert.<br />

e<strong>in</strong>e Funktion ist auch e<strong>in</strong> Block<br />

dynamische Lebensdauer: Der Speicherbereich wird mittels<br />

Bibliotheksfunktionen angelegt und freigegeben (malloc und<br />

free).<br />

<strong>E<strong>in</strong>führung</strong> <strong>in</strong> <strong>die</strong> <strong>Programmierung</strong> Gültigkeitsbereiche 35 / 41<br />

Speicherklasse<br />

Die Speicherklasse e<strong>in</strong>es Objekts hat E<strong>in</strong>fluss auf<br />

<strong>die</strong> Lebensdauer und<br />

den Gültigkeitsbereich des Objekts und<br />

erlaubt E<strong>in</strong>schränkungen für den Zugriff auf Daten.<br />

<strong>E<strong>in</strong>führung</strong> <strong>in</strong> <strong>die</strong> <strong>Programmierung</strong> Gültigkeitsbereiche 37 / 41<br />

Speicherklasse: extern<br />

In der Regel ist Datenaustausch über e<strong>in</strong>e Parameterliste<br />

gegenüber globalen Variablen vorzuziehen:<br />

Global gültige Daten führen oft zu Programmen mit vielen,<br />

schwer durchschaubaren Datenpfaden zwischen Funktionen<br />

(mit unerwünschten Nebenwirkungen).<br />

Der Aufbau von Bibliotheken mit allgeme<strong>in</strong> gültigen<br />

Funktionen ist nicht möglich.<br />

Weniger Fehleranfällig: Pr<strong>in</strong>zip der Datenkapselung<br />

Daten s<strong>in</strong>d nur <strong>in</strong>nerhalb e<strong>in</strong>es Moduls sichtbar<br />

Zugriff auf Daten nur über def<strong>in</strong>ierte Zugriffsmethoden<br />

mehr dazu später<br />

<strong>E<strong>in</strong>führung</strong> <strong>in</strong> <strong>die</strong> <strong>Programmierung</strong> Gültigkeitsbereiche 39 / 41<br />

Gültigkeitsbereich von Bezeichnern<br />

<strong>in</strong>t global; // gilt bis zum Ende der Datei<br />

// x: gilt nur <strong>in</strong>nerhalb der Klammern<br />

double s<strong>in</strong>(double x);<br />

<strong>in</strong>t ma<strong>in</strong>(<strong>in</strong>t argc, char *argv[]) {<br />

<strong>in</strong>t lokal; // gilt nur <strong>in</strong>nerhalb von ma<strong>in</strong><br />

...<br />

for (i = 0; i < 10; i++) {<br />

<strong>in</strong>t j; // gilt nur <strong>in</strong>nerhalb des Blocks<br />

for (j = 0; j < i; j++) {<br />

...<br />

}<br />

}<br />

}<br />

// Label ende gilt nur <strong>in</strong>nerhalb von ma<strong>in</strong><br />

ende: ...<br />

<strong>E<strong>in</strong>führung</strong> <strong>in</strong> <strong>die</strong> <strong>Programmierung</strong> Gültigkeitsbereiche 34 / 41<br />

Lebensdauer von Objekten<br />

void fkt(<strong>in</strong>t x) {<br />

static <strong>in</strong>t s = 1; // statische Lebensdauer<br />

<strong>in</strong>t a = 1; // automatische Lebensdauer<br />

}<br />

pr<strong>in</strong>tf("x= %d, s= %d, a= %d\n", x, s++, a++);<br />

<strong>in</strong>t ma<strong>in</strong>(void) {<br />

<strong>in</strong>t i, *p;<br />

}<br />

p = (<strong>in</strong>t *) malloc(10 * sizeof(<strong>in</strong>t));<br />

for (i = 0; i < 10; i++) {<br />

p[i] = i + 1; // dynamische Lebensdauer<br />

fkt(p[i]);<br />

}<br />

free(p);<br />

return 0;<br />

<strong>E<strong>in</strong>führung</strong> <strong>in</strong> <strong>die</strong> <strong>Programmierung</strong> Gültigkeitsbereiche 36 / 41<br />

Speicherklasse: extern<br />

Variablen, <strong>die</strong> außerhalb von Funktionen deklariert werden, s<strong>in</strong>d<br />

implizit vom Typ extern.<br />

Lebensdauer: Für <strong>die</strong> gesamte Laufzeit des Programms wird<br />

Speicherplatz reserviert.<br />

Gültigkeit: Globale Variablen gelten von dem Punkt, an dem sie<br />

vere<strong>in</strong>bart werden, bis zum Ende der Datei.<br />

E<strong>in</strong> Objekt e<strong>in</strong>er externen Deklaration ist beim B<strong>in</strong>den auch<br />

Programmteilen aus anderen Dateien bekannt.<br />

<strong>E<strong>in</strong>führung</strong> <strong>in</strong> <strong>die</strong> <strong>Programmierung</strong> Gültigkeitsbereiche 38 / 41<br />

Speicherklasse: static<br />

Anwendung bei<br />

Funktionen: Die Funktion ist nur <strong>in</strong>nerhalb der Quelldatei und<br />

nicht dem L<strong>in</strong>ker bekannt (siehe Modulare <strong>Programmierung</strong>,<br />

Datenkapselung).<br />

lokale Variablen: Objekte behalten ihren Wert auch nach<br />

Verlassen des Blocks, <strong>in</strong> dem sie def<strong>in</strong>iert s<strong>in</strong>d.<br />

globale Variablen: E<strong>in</strong>schränkung des Gültigkeitsbereichs auf<br />

<strong>die</strong> Datei.<br />

Gültigkeit: <strong>in</strong>nerhalb des umschließenden Blocks bzw. bei<br />

Funktionen und globalen Variablen <strong>in</strong>nerhalb der Datei.<br />

<strong>E<strong>in</strong>führung</strong> <strong>in</strong> <strong>die</strong> <strong>Programmierung</strong> Gültigkeitsbereiche 40 / 41


Speicherklasse: static<br />

dat1.c:<br />

void f(void) {<br />

extern <strong>in</strong>t i;<br />

...<br />

}<br />

static <strong>in</strong>t i;<br />

<strong>in</strong>t j;<br />

void g(void) {<br />

i = 42;<br />

j = 4711;<br />

...<br />

}<br />

sehr schlechter Programmierstil!<br />

dat2.c:<br />

void h(void) {<br />

extern <strong>in</strong>t j; // ok<br />

extern <strong>in</strong>t i; // Fehler!<br />

}<br />

i += 42;<br />

j += 4711<br />

<strong>E<strong>in</strong>führung</strong> <strong>in</strong> <strong>die</strong> <strong>Programmierung</strong> Gültigkeitsbereiche 41 / 41

Hurra! Ihre Datei wurde hochgeladen und ist bereit für die Veröffentlichung.

Erfolgreich gespeichert!

Leider ist etwas schief gelaufen!