Praktische Informatik I
© Prof. Dr. W. Effelsberg
6. Die Programmiersprache C 6-1
6 Die Programmiersprache C
6.1 Datentypen und Deklarationen 6.2 Operatoren und Ausdrücke
6.3 Ablaufsteuerung (Kontrollstrukturen) 6.4 Unterprogramme
6.5 Zeiger und komplexe Datenstrukturen 6.6 Dateien, Ein- und Ausgabe
6.7 Weitere Sprachkonstrukte
6.8 Die Umgebung von C-Programmen 6.9 Beispiel
Die Bedeutung der Sprache C
• C ist die "Muttersprache" von UNIX
• C ist hochgradig portierbar und standardisiert (ANSI:
X3.159-1989)
• C ermöglicht eine sehr effiziente, maschinennahe Programmierung
• C Schlägt die Brücke von Java zu Assembler- Programmierung
• Aber: C erlaubt viele „unsaubere“ Programmiertricks
Literatur
Karlheinz Zeiner
"Programmieren lernen mit C"
Carl Hanser Verlag 1994
Kernighan/Ritchie
Praktische Informatik I
© Prof. Dr. W. Effelsberg
6. Die Programmiersprache C 6-3
6.1 Datentypen und Deklarationen
Es gibt elementare Datentypen, z.B. zur Beschreibung von Zahlen oder einzelnen Zeichen, und es gibt kom- plexe Datentypen, z.B. zur Beschreibung von verkette- ten Listen oder von Datenstrukturen bestehend aus ver- schiedenen Komponenten.
Merke: In C müssen alle Daten vor ihrer Verwendung vereinbart (deklariert) werden, wie in Java, anders als z.B. in Fortran oder Basic.
Ein C-Programm setzt sich aus Vereinbarungen und Anweisungen zusammen. Die Anweisungen definieren die Kontrollstruktur eines Programms. Die Vereinbarun- gen beinhalten die Datenstrukturen, auf denen ein Pro- gramm arbeitet.
Aufbau eines C-Programms
int
main
( int
argc , char *
argv []
Vereinbarungen und Anweisungen }
Hauptprogramm
)
{ void
argc und argv stellen die Verbindung des Programms zu seiner Umwelt her. Hier wird die Anzahl der Argu-
Praktische Informatik I
© Prof. Dr. W. Effelsberg
6. Die Programmiersprache C 6-5
Vereinbarungen in C – Programmen (1)
Vereinbarungen
Konstantenvereinbarung Typenvereinbarung
Variablenvereinbarung
Routinenvereinbarung
Vereinbarungen in C-Programmen (2)
Merke: Die im Syntaxdiagramm angegebene Reihenfol- ge der Vereinbarungen ist nicht zwingend vorgeschrie- ben. Es ist jedoch sinnvoll, sich an diese Reihenfolge zu halten.
In C gibt es zwei Arten von Vereinbarungen:
• Vereinbarungen, die Speicherplatz reservieren (Defi- nitionen), z.B. Variablenvereinbarungen, Routinen- definitionen
• Vereinbarungen, die eine Variable/einen Daten- typ/eine Routine beschreiben (Deklarationen)
z.B. Typvereinbarungen, Prototypen von Routinen.
Praktische Informatik I
© Prof. Dr. W. Effelsberg
6. Die Programmiersprache C 6-7
Typvereinbarung
Typvereinbarung
typedef Typ Typname ;
,
typedef dient zur Definition eigener Datentypen als Ableitung aus bestehenden Datentypen.
Beispiel
typedef int alter;
alter lebensalter, firmenbestand;
Vordefinierte Datentypen in C
einfacher Typ
strukturierter Typ
Zeigertyp Typ
Hinweis: strukturierte Typen und Zeigertypen werden wir später erklären.
Praktische Informatik I
© Prof. Dr. W. Effelsberg
6. Die Programmiersprache C 6-9
Einfache Datentypen
einfacher Typ
elementarer Datentyp
Aufzählungstyp
Elementare Datentypen
elementare Datentypen
signed
char
unsigned
int
short
long
float
double
long double int
int
Praktische Informatik I
© Prof. Dr. W. Effelsberg
6. Die Programmiersprache C 6-11
Beschreibung der elementaren Datentypen
integer
• unsigned int = natürliche Zahlen inclusive 0, als Bi- närzahlen abgespeichert.
• (signed) int = Ganzzahlen, in der Regel in Zweier- komplementdarstellung abgespeichert.
Beispiel:
Bits unsigned signed
000 0 0
001 1 1
010 2 2
011 3 3
100 4 -4
101 5 -3
110 6 -2
111 7 -1
N = Anzahl Bits
Wertebereich unsigned: 0 bis 2N - 1 Wertebereich signed: -2N-1 bis 2N-1 – 1
Ganze Zahlen unterschiedlicher Länge
char/short/long int
Datentypen für ganze Zahlen unterschiedlicher Länge.
Es gilt:
len(char) ≤ len(short) ≤ len(int) ≤ len(long)
In der Regel belegt char 8 Bits (1 Byte), short 16 Bits (2 Bytes) und int 32 Bits (4 Bytes). Dies ist jedoch ab- hängig vom Compiler.
Praktische Informatik I
© Prof. Dr. W. Effelsberg
6. Die Programmiersprache C 6-13
Zeichen (1)
Der Datentyp char
Für den Datentyp char gilt, daß der Wertebereich aus diskreten Einzelwerten besteht, die einer Ordnungsrela- tion unterliegen. Zeichen werden in einem Byte gespei- chert und auf ganze Zahlen abgebildet.
Im ASCII-Code entspricht beispielsweise '0' der Zahl 48, 'A' der Zahl 65 und 'a' der Zahl 97.
Für Steuerzeichen gibt es in C eine Ersatzdarstellung.
Der backslash (\) wird dabei als Escape-Zeichen be- zeichnet, welches "die normale Interpretationsebene verlässt".
Beispiele
\n steht für Zeilenvorschub
\g steht für Glocke
\t steht für Tabulator.
Zeichen (2)
Die Ordnung der Zeichen untereinander (die Kollati- onsfolge) ist in C implementierungsabhängig. Der
Standard fordert lediglich, dass die Ziffern 0 – 9 aufstei- gend und lückenlos angeordnet sind sowie dass die Großbuchstaben und die Kleinbuchstaben in alphabeti- scher Reihenfolge angeordnet sind. Eine Ordnung zwi- schen der Menge der Großbuchstaben und der Menge der Kleinbuchstaben ist beispielsweise nicht vorge- schrieben.
Praktische Informatik I
© Prof. Dr. W. Effelsberg
6. Die Programmiersprache C 6-15
Gleitkommazahlen (1)
float/double/long double
Die Datentypen float, double und long double werden zur Darstellung von reellen Zahlen verwendet. Der im Prinzip kontinuierliche Zahlenbereich der reellen Zahlen kann im Computer nicht vollständig dargestellt werden, da hierzu unendlich viele Codewörter benötigt würden.
Man kann nur rationale Zahlen mit einer begrenzten An- zahl von Stellen darstellen. Dazu werden reelle Zahlen ins Dualsystem übertragen und in Gleitpunktdarstellung mit Vorzeichen, Mantisse und Exponent gespeichert.
Beispiel
5.75 = 4 + 0 + 1 + 0.5 + 0.25
= 1*22 + 0*21 + 1*20 + 1*2-1 + 1*2-2
= 101.11
= 0.10111 * 23
Gleitkommazahlen (2)
Eine Gleitkommazahl erfordert also die maschineninter- ne Codierung
• der Mantisse
• des Vorzeichens der Mantisse
• des Exponenten
• des Vorzeichens des Exponenten.
Dazu gibt es verschiedene Konventionen; die bekannte- ste ist die von IEEE (Standard 754).
Folgende Grenzwerte müssen von einem C-Compiler mindestens eingehalten werden:
Typ kleinste Zahl größte Zahl Genauigkeit float
double
1E-37 1E-37
1E+37 1E+37
1E-5 1E-9
Praktische Informatik I
© Prof. Dr. W. Effelsberg
6. Die Programmiersprache C 6-17
Wahrheitswerte
Jede ganze Zahl x kann in C einen Wahrheitswert dar- stellen. Dabei gilt per Konvention:
x = 0 impliziert x = false
x ≠ 0 impliziert x = true
Falls ein Wahrheitswert auf eine ganze Zahl abgebildet werden soll, gilt:
false entspricht x = 0
true entspricht x = 1
Aufzählungstyp (enumeration type) (1)
Eine Aufzählung ist eine Folge von Zeichenkonstanten, denen vom Compiler jeweils ein Integer-Wert zugeord- net wird.Syntax
enum Typname { Enum-
erator } ;
, Aufzählungstyp
Beispiel
enum fruit {apple = 7, pear, orange = 3, lemon, peach}
Nun gilt: apple = 7, pear = 8, orange = 3, lemon = 4, pe- ach = 5.
Merke:
Praktische Informatik I
© Prof. Dr. W. Effelsberg
6. Die Programmiersprache C 6-19
Konstantenvereinbarung
In C gibt es zwei Möglichkeiten, Konstanten zu verein- baren:
• const-Vereinbarung
Die const-Vereinbarung definiert eine Variable, die nur gelesen und nicht zugewiesen werden darf. Die Verwendung zur Definition der Länge einer anderen Datenstruktur (z.B. einer Vektorlänge) ist deshalb syntaktisch nicht erlaubt.
• #define-Klausel
#define suchtext ersatztext
Die #define-Klausel definiert sogenannte Compiler- Konstanten. Beim Übersetzen wird im gesamten Pro- grammcode der Suchtext durch den Ersatztext er- setzt. Wenn man also Suchtext als Konstantenname und Ersatztext als Konstante ansieht, hat man eine Compiler-Konstante. Bei #define können als Kon- stanten auch Ausdrücke eingesetzt werden.
Beispiel
#define max_length 1000 int a [max_length];
Syntax für Konstante in C
Konstanten-Vereinbarung
const Konstanten-
name
Konstante
Konstante
Zahl
Zeichen
Zeichenkette
Typ =
;
Praktische Informatik I
© Prof. Dr. W. Effelsberg
6. Die Programmiersprache C 6-21
Beispiele für Konstantenvereinbarungen (1)
Zahlen
const float pi = 3.14159;
const int ganze_Zahl = 79;
const int hexa_Zahl = 0x13;
Zeichen
const char anfang = "a";
Zeichenkette
const char alphabet = "abc";
Variablenvereinbarung
Variablenvereinbarung
Typ Variablen-
name
;
,
Initiali- sierung
Beispiele
int anz_kinder;
float groesse;
char initiale_vorname, initiale_nachname;
Konstante vom Typ der Variablen
=
Initialisierung
Beispiel
Praktische Informatik I
© Prof. Dr. W. Effelsberg
6. Die Programmiersprache C 6-23
6.2 Operatoren und Ausdrücke
Ausdruck (expression)
• Verarbeitungsvorschrift zur Ermittlung eines Wertes
• besteht aus Operanden und Operatoren
• wichtigste Ausdrücke: arithmetische und logische (boole'sche) Ausdrücke
Beispiele
int i = 5, j = 2, k =23;
float x = 2.0, y = 5.5;
double d = 2.4;
Ausdruck Resultat i / j
k % i*j k – 7 % 5
x*y -i y / x y % x
d / 2
2 6 21 6.0 2.75
nicht erlaubt 1.2
Regeln
• Bei der Auswertung gelten, wie üblich, Vorrangregeln, z.B. Punktrechnung vor Strichrechnung
• a / b ergibt für int a,b wiederum einen int-Wert, nämlich den Ganzzahl-Anteil der Division
• a % b (die modulo-Funktion) ist auf float und dou- ble nicht erlaubt
• bei Mischung von int und float/double in einem Ausdruck ist das Resultat vom Typ float/double.
Praktische Informatik I
© Prof. Dr. W. Effelsberg
6. Die Programmiersprache C 6-25
Der L-Wert (1)
Ein L-Wert ist ein Ausdruck, der einen benannten Spei- cherbereich bezeichnet. L-Werte sind Objekte, denen Ergebnisse von Operationen zugeordnet werden kön- nen. Ein Beispiel für einen L-Wert ist ein Variablenname mit geeignetem Typ und passender Speicherklasse.
Manche Operatoren erwarten L-Werte als Operanden, manche liefern einen L-Wert als Resultat.
Beispiele
&lvalue Adressoperator
*expression Inhaltsoperator (liefert L-Wert)
Der L-Wert (2)
L-Wert
Bezeichner
Bezeichner
Bezeichner
Bezeichner Bezeichner
Ausdruck
Ausdruck L-Wert
L-Wert
*
( )
->
.
[ ]
Praktische Informatik I
© Prof. Dr. W. Effelsberg
6. Die Programmiersprache C 6-27
Arithmetische Operatoren
+ − * / %
arithmetischer Ausdruck
Ausdruck 1 arithm. Operatoren Ausdruck 2
arithmetischer Operator
Beispiel a+b
(x-y) / (z%5)
Zuweisungsoperator
Zuweisung
L-Wert Zuweisungs-
operator Ausdruck ;
Zuweisungsoperator
+ - * / % >> <<
=
Beispiele a += 5
l[a] = 17+4 a = b = c = 7
Praktische Informatik I
© Prof. Dr. W. Effelsberg
6. Die Programmiersprache C 6-29
Unäre Ausdrücke
Unärer Ausdruck
unärer arithmetischer Ausdruck
Postfix-Arithmetik
Prefix-Arithmetik
Inhalts- Operator
Cast- Operator
Sizeof- Operator
Unärer arithmetischer Ausdruck
Syntax
unärer arithmetischer Ausdruck
+ - ! ~
Ausdruck
*
+ (a+b) - (x*y)
Vorzeichen
!a logische Negation (NOT)
*a Inhaltsoperator
~a bitweise Negation
L-Wert Adreßoperator
&
Praktische Informatik I
© Prof. Dr. W. Effelsberg
6. Die Programmiersprache C 6-31
Inkrement/Dekrement (1)
Syntax
Postfixarithmetik
L-Wert
++
-- Prefixarithmetik
L-Wert ++
--
Inkrement/Dekrement (2)
Postinkrement
Wert der Variablen wird erst nach Auswertung des Aus- drucks, in dem die Variable vorkommt, erhöht.
Preinkrement
Wert der Variablen wird vor Auswertung des Ausdrucks, in dem die Variable vorkommt, erhöht.
Beispiel für das Postinkrement int a, b;
a = 1;
b = a++;
/* b=1, a=2 */
Beispiel für das Preinkrement int a,b;
a = 1;
b = ++a;
Praktische Informatik I
© Prof. Dr. W. Effelsberg
6. Die Programmiersprache C 6-33
Typkonversionsoperator (type cast)
Syntax
cast - Operator
( Typname ) Ausdruck
In C gibt es keine strenge Bindung der Variablen an ihre Datentypen! Treffen in einer Operation Operanden mit unterschiedlichem Datentyp zusammen, so wandelt C nach definierten Regeln implizit um. Ist die Umwand- lungsregel nicht offensichtlich (z.B. int ->float), so sollte explizit konvertiert werden, um anzuzeigen, wie die
Konvertierung erfolgen soll.
Beispiel int a;
double x;
a = (int) (5 * x);
Der sizeof - Operator
Syntax
sizeof - Operator
Typname
Ausdruck
sizeof (
)
C verwendet den unären Operator sizeof, um die Anzahl von Bytes zu bestimmen, die zur Speicherung eines
Objektes benötigt werden.
Beispiele int a;
sizeof (char) liefert in der Regel 1 sizeof (a*2) liefert sizeof (int)
Praktische Informatik I
© Prof. Dr. W. Effelsberg
6. Die Programmiersprache C 6-35
Vergleichsoperatoren (1)
Syntax
Vergleich
Gleichheitsoperator
Relationsoperator
Gleichheitsoperator
Ausdruck 1 Ausdruck 2
==
Relationsoperator
Ausdruck 1
Ausdruck 2
>
< < = >=
!=
Vergleichsoperatoren (2)
Die Rangordnung der Relationsoperatoren ist kleiner als die der arithmetischen Operatoren.
Die Rangordnung der Gleichheitsoperatoren ist kleiner als die der Relationsoperatoren.
Das Ergebnis von Vergleichsoperatoren ist ein Wahr- heitswert.
Beispiele a ==b y >= z
Praktische Informatik I
© Prof. Dr. W. Effelsberg
6. Die Programmiersprache C 6-37
Logische Operatoren
Syntax
logische Verknüpfung
Ausdruck 1 Ausdruck 2
&&
Die Präzedenz von && ist höher als die von ||, aber bei- de haben einen niedrigeren Rang als unäre, arithmeti- sche und Vergleichsoperatoren. Lediglich die Zuwei- sungsoperatoren haben einen noch niedrigeren Rang
Der Komma-Operator
Syntax
Komma - Ausdruck
Ausdruck 1 , Ausdruck 2
Zwei Ausdrücke werden nacheinander von links nach rechts ausgeführt. Datentyp und Resultat des Ausdrucks sind vom Typ und Wert von Ausdruck 2.
Beispiel
for ( s = 0, i = 0; i< n; i++) s += x [i];
Praktische Informatik I
© Prof. Dr. W. Effelsberg
6. Die Programmiersprache C 6-39
Bitoperatoren (1)
Die kleinste adressierbare Speichereinheit in C ist ein Byte (char). Es ist aber möglich, auch einzelne Bits zu manipulieren. Dies erfolgt mit Hilfe der Bitoperatoren.
Bitweise logische Operatoren
Aktion Symbol
Bitweises Komplement ~ Bitweises AND
&
Bitweises OR |
Bitweises XOR ^
Shift-Operatoren
LEFTSHIFT <<
RIGHTSHIFT >>
Bitoperatoren (2)
Der Operator ~ ist als einziger Bitoperator unär (einstel- lig). Er bildet das bitweise Komplement.
Beispiel
x = (int) 5 (dezimal)
⇒ x = 0x0000000000000101 (hexadezimal)
⇒ ~x = 0x1111111111111010 (hexadezimal)
Die anderen Operatoren sind binäre (zweistellige) Ope- ratoren und arbeiten, wie in der Aussagenlogik definiert.
Beispiel
x = 0x1100; y = 0x1010;
x ^ y ergibt 0x0110 (XOR-Operator)
Praktische Informatik I
© Prof. Dr. W. Effelsberg
6. Die Programmiersprache C 6-41
Bitoperatoren (3)
Die Shiftoperatoren verschieben den gesamten Bits- tring um n Bits nach rechts oder links. So lässt sich z.B.
auch leicht eine 2er-Multiplikation/Division implementie- ren.
Beispiel
x = 0x0101 (= 5 dezimal) x << 1 ergibt 0x1010 (=10 dezimal)
Merke: Es kommt leicht zu Verwechselungen von & mit
&&. Dies kann fatale Auswirkungen haben!
Beispiel
unsigned short int x = 2; /* Länge = 1 Byte */
x && 1 liefert als Ergebnis 0 oder 1 zurück,
abhängig von x (Wert ≠ 0 wird als Wahr- heitswert true interpretiert)
x & 1 liefert
00000010 00000001 00000000
Ausdruck
einfacher Ausdruck Ausdruck
unärer Ausdruck
arithmetischer Ausdruck Zuweisung
Vergleich
logische Verknüpfung
Bit - Ausdruck
Komma - Ausdruck
Praktische Informatik I
© Prof. Dr. W. Effelsberg
6. Die Programmiersprache C 6-43
Bedingter Ausdruck
Syntax
Ausdruck 1 ? Ausdruck 2 : Ausdruck 3
bedingter Ausdruck
Der Code ist äquivalent zu
x = (y < z) ? y : z; if (y < z) x = y;
else
x = z;
Beispiel
max = (a < b) ? b : a;
Präzedenzregeln
Die Präzedenzregeln (Rangordnung der Operatoren) sind (wie üblich) an die Gepflogenheiten der Mathematik angelehnt.
• Geklammerte Ausdrücke zuerst
• Ungeklammerte Ausdrücke gemäß vier Präzedenz- klassen:
1.) NOT
2.) Multiplikationsoperatoren 3.) Additionsoperatoren
4.) Vergleichsoperatoren
• bei gleicher Präzedenz erfolgt die Abarbeitung von links nach rechts
Beispiele
a) (3 <= 8 * 8 + 4) || (9 / 3 + 4 * 3 <= 10) = (3 <= 68) || (15 <=
10)
=1 || 0
=1 (TRUE)
b) 3 - 8 + 4 *2 - 9 / 2 % 3*2 + 1 = 3 - 9 / 2 % 3 * 2 + 1
Praktische Informatik I
© Prof. Dr. W. Effelsberg
6. Die Programmiersprache C 6-45
Überlauf/Unterlauf bei ganzen Zahlen
Auch ganze Zahlen (integers) haben wegen der be-grenzten Wortlänge des Computers einen beschränkten Wertebereich (z.B. 32 Bits). Ein Ganzzahl-
Überlauf/Unterlauf tritt bei Verlassen des Wertebereichs auf.
Sei z eine ganze Zahl (also vom Datentyp int).
Dann gilt:
min ≤ z ≤ max , min < max,
wobei min und max den zulässigen Wertebereich für z begrenzen.
Beispiele für Überläufe
Merke: Damit bei arithmetischen Operationen das Er- gebnis korrekt ist, müssen auch alle Zwischenresultate innerhalb des zulässigen Wertebereiches bleiben!
Sei -min = max = 1000.
700 + 400 - 200 80 * 20 / 4
erzeugen Überläufe in Zwischenresultaten, wenn sie von links nach rechts ausgewertet werden. Solche
Überläufe können unter Umständen durch Klammerung vermieden werden:
700 + (400 - 200) 80 * (20 / 4)
Manche Compiler kümmern sich bereits selbst um eine solche Änderung der Reihenfolge der Auswertung. Man kann sich jedoch nicht darauf verlassen!
Man könnte sagen: Das Assoziativgesetz gilt nicht mehr, wenn Bereichsgrenzen überschritten werden.
Praktische Informatik I
© Prof. Dr. W. Effelsberg
6. Die Programmiersprache C 6-47
Operatoren (1)
Rang Art Symbol
in der Logik/
Arith- metik
Ope- rator in C
Name Beispiel
1 ( ) ( ) Klammern (a+b)
1 monadisch [ ] [ ] Array/
Vektor
a[ ]
1 monadisch -> Kompo-
nente
a-> b
1 monadisch . Kompo-
nente
a . b 2 monadisch/
arithmetisch
++ Addition von 1
a++
monadisch/
arithmetisch
-- Subtraktion von 1
--b 2 monadisch/
logisch
¬ ! Negation !treu
2 monadisch/
logisch
NOT ~ Bitkom-
plement
~y
2 monadisch (type) typecast (int) x
2 monadisch sizeof sizeof si-
zeof(int)
Operatoren (2)
2 monadisch/arithmetisch
+ + Plusvorzei-
chen
+7 monadisch/
arithmetisch
- - Minusvorzei-
chen
-7
2 monadisch * Verweis *a
2 monadisch & Adresse &a
3 dyadisch/
arithmetisch
* * Multiplikatin 3*4
dyadisch/
arthimetisch/
/ / Division 3 / 4
dyadisch/
arithmetisch
DIV / ganzz. Divi- sion
3 / 4 = 0 dyadisch/
arithmetisch
MOD % ganzz. Rest 3%4 = 3 4 dyadisch/
arithmetisch
+ + Addition 3+4
dyadisch/
arithmetisch
- - Subtraktion 3-4
5 dyadisch/ LSHIFT << Linksshift um x<<5
Praktische Informatik I
© Prof. Dr. W. Effelsberg
6. Die Programmiersprache C 6-49
Operatoren (3)
6 dyadisch < < Relation- soperatoren
a>b
dyadisch ≤ <=
dyadisch > >
dyadisch ≥ >=
7 dyadisch ==
=!
==
=!
Gleichheits- operatoren
a==b 8 dyadisch/ lo-
gisch
^ & Logisches
`und` auf Bits
x & y
9 dyadisch/ lo- gisch
XOR ^ Logisches
`XOR` auf Bits
x ^ y
10 dyadisch/ lo- gisch
∨ | Logisches
`oder` auf Bits
x | y
11 dyadisch/
logisch
∧ && logisches 'und'
a && b 12 dyadisch/
logisch
∨ || logisches
'oder'
a || b
13 ?: bedingter
Ausdruck
a ? c : b
Operatoren (4)
14 =
+=
-=
*=
/=
%=
&=
^=
|=
<<=
>>=
Wertzu- weis-ung
15 , Kommaope-
rator
s=0, i=0
Praktische Informatik I
© Prof. Dr. W. Effelsberg
6. Die Programmiersprache C 6-51
6.3 Ablaufsteuerung (Kontroll struktren)
• Sequenz von Anweisungen (Hintereinander- Ausführung)
• Selektion
• if ... else
• switch ...
• Iteration
• while ...
• do... while ...
• for ...
6.3.1 Anweisungen
Ein Programm besteht aus einer Folge von Anweisun- gen.
Anweisung
leere Anweisung Zuweisung Routinen-Aufruf Anweisungsblock Iterations-Anweisung Auswahl-Anweisung Anweisung mit Marke
Sprung-Anweisung
Praktische Informatik I
© Prof. Dr. W. Effelsberg
6. Die Programmiersprache C 6-53
Wertzuweisung
("Ergibt - Anweisung", assignment statement)
• Berechnung des rechts stehenden Ausdrucks
• Wertzuweisung an die links stehende Variable
Syntax
Zuweisung
L-Wert Zuweisungs-
operator Ausdruck ;
Merke: Der Ausdruck sollte stets denselben Datentyp haben wie die Variable; wenn dies nicht sowieso der Fall ist, sollte ein Typecast programmiert werden!
Beispiel
summe += 4; /*identisch zu summe = summe +4;*/
produkt *= i; /*identisch zu produkt = produkt * i;*/
Da in C Zuweisungen syntaktisch selbst Ausdrücke sind, sind "Mehrfachzuweisungen" (verkettete Zuwei- sungen) in C möglich!
Beispiele
a = b = c = 0.0;
if ((c=getc(datei))!= EOF) ...
[Man beachte die Klammerung wegen der Vorrangregel]
Die Initialisierung mehrerer Werte in einer Anweisung und die Verwendung als Operand in einem Aufruf sind typische Anwendungen.
Praktische Informatik I
© Prof. Dr. W. Effelsberg
6. Die Programmiersprache C 6-55
Wertzuweisung ungleich Vergleichsoperator!
i = i + 1; ist eine Wertzuweisung an i;
Neuer Wert ist alter Wert + 1
i == i + 1 ist ein boole'scher Ausdruck, der immer falsch ist!
Syntaktisch ist auch dieser Ausdruck kor- rekt. Er kann ersetzt werden durch 0 (fal- se).
Häufige Ursache von Programmierfehlern!
Beispiele für Wertzuweisungen
Die Variablen seien wie folgt deklariert:
int i, j, k;
double x, y, z;
int fertig;
i = j / k + i;
z = x / y;
fertig = (z < j) && ! (x == y);
i = j / x; implizite Typkonvertierung! */
i = z / x + 15; implizite Typkonvertierung */
fertig = 1 && x; zugewiesen wird 0 oder 1! */
Praktische Informatik I
© Prof. Dr. W. Effelsberg
6. Die Programmiersprache C 6-57
Folgen von einfachen Anweisungen (Sequenz)
Folge von Anweisungen, sequentiell aufgeschrieben, getrennt durch ";"Anweisung
Sequenz
Beispiele
a = b; x = y + 3; z = 17;
a = 3 * 87 - 5;
wahr = (x < 5) || (y > 20);
Anweisungsblock
Anweisungsblock
Deklaration Anweisungs- Sequenz
{ }
Ein Anweisungsblock kann überall da stehen, wo eine einfache Anweisung stehen kann, insbesondere
• in Abhängigkeit von einer Bedingung
• im Rumpf einer Schleife.
Der gesamte ausführbare Teil eines C-Programms kann als Anweisungsblock aufgefasst werden.
In C kann zu Beginn jedes Anweisungsblocks eine Va- riablendeklaration eingefügt werden. Die hier deklarier- ten Variablen sind jedoch nur innerhalb dieses Blockes
Praktische Informatik I
© Prof. Dr. W. Effelsberg
6. Die Programmiersprache C 6-59
6.3.2 Bedingte Anweisung
if-Anweisung
if Ausdruck Anweisung
else Anweisung
( )
Anmerkungen zur bedingten Anweisung
Anmerkung 1
Als "Anweisung" tritt häufig ein Anweisungsblock der Form
{
Anweisung;
Anweisung;
. .
Anweisung;
}
auf, die dann als Ganzes von der Bedingung abhängt.
Anmerkung 2
Eine bedingte Anweisung der Form if Ausdruck Anweisung;
Anweisung;
else Anweisung;
ist syntaktisch falsch!
Praktische Informatik I
© Prof. Dr. W. Effelsberg
6. Die Programmiersprache C 6-61
Geschachtelte if - Anweisungen
Die Zugehörigkeit der else-Klausel zur if-Klausel wird üblicherweise durch Einrückung deutlich gemacht. Die Einrückung ist aber nicht signifikant für den Compiler!
Regel
Ein else gehört immer zu dem letzten if, das noch keine else - Klausel hat.
Beispiel: Knobelspiel
Zwei Spieler geben unabhängig voneinander gleichzei- tig je eine nicht-negative ganze Zahl an (etwa durch Ausstrecken von Fingern auf Kommando oder durch verdecktes Aufschreiben).
Nennen beide Spieler die gleiche Zahl, so endet das Spiel unentschieden; andernfalls gewinnt, falls die Summe der genannten Zahlen gerade ist, der Spieler, der die kleinere Zahl genannt hat, und sonst (falls also die Summe ungerade ist) derjenige, der die größere Zahl genannt hat.
Praktische Informatik I
© Prof. Dr. W. Effelsberg
6. Die Programmiersprache C 6-63
Erster Entwurf
/* PROGRAMM knobelspiel */void main () {
/* Variablen deklarieren */
/* ... */
if (eingabe fehlerhaft) {fehlermeldung}
else
{Entscheidung}
}
Schrittweise Verfeinerung
Die Entscheidung lässt sich schreiben als if {eingaben gleich}
{unentschieden}
else {ermittle sieger}
Der Sieger kann ermittelt werden mit if {summe gerade}
{kleinerer siegt}
else {grösserer siegt}
Um anzugeben, welcher der beiden gewonnen hat, kann man den Sieg des Spielers mit der kleineren Zahl be- schreiben als
if {erster spieler kleinere zahl}
{erster spieler siegt}
else {zweiter spieler siegt}
Der Sieg des Spielers mit der größeren Zahl wird be-
Praktische Informatik I
© Prof. Dr. W. Effelsberg
6. Die Programmiersprache C 6-65
Programm "Knobelspiel" in Pseudo-Code
/* PROGRAMM knobelspiel *//* Variablendeklaration */
void main () { {eingabe}
if {eingabe fehlerhaft}
{fehlermeldung}
else
if {eingaben gleich}
{unentschieden}
else
if {summe gerade}
if{erster Spieler kleinere zahl}
{erster spieler siegt}
else {zweiter spieler siegt}
else {summe ungerade}
if {erster spieler grössere zahl}
{erster spieler gewinnt}
else {zweiter spieler siegt}
} /* main */
(In unserer Notation im Pseudocode ist vereinbarungs- gemäß die Einrückung signifikant.)
Programm "Knobelspiel" in C
/* PROGRAMM knobelspiel */
void main () { int k,l;
printf ("Bitte die beiden Knobelwerte einge- ben:");
scanf ("%d \n", &k); scanf ("%d \n", &l);
/* "call by reference", Erklärung folgt später */
if (( k < 0) || (l < 0))
printf ("unzulässige eingabe");
else
if (k == l)
printf ("unentschieden");
else
if (((k + l) %2) !=0) /*ungerade Summe*/
if k < l)
printf ("1. spieler siegt");
else printf ("2. spieler siegt");
else
Praktische Informatik I
© Prof. Dr. W. Effelsberg
6. Die Programmiersprache C 6-67
6.3.3 Mehrfach-Selektion (Fallunterscheidung)
Die Mehrfachselektion ist eine Auswahlanweisung mit mehreren Alternativen. Es wird untersucht, ob ein Aus- druck einen aus einer Liste von mehreren konstanten ganzzahligen Werten besitzt, dann wird entsprechend verzweigt.Syntax der Mehrfach-Selektion
Mehrfachauswahl
switch ( Ausdruck ) { Listenelement }
Listenelement
Marke Anweisung break ;
default
:
Marke
case Konstante
Praktische Informatik I
© Prof. Dr. W. Effelsberg
6. Die Programmiersprache C 6-69
Beispiel für
switchvoid main () {
typedef enum {sieben, acht, neun, zehn, bube, dame, könig, as} spielkartentyp ;
spielkartentyp karte;
int wert;
switch (karte) {
case sieben : wert = 7;
break;
case acht : wert = 8;
break;
case neun : wert = 9;
break;
case zehn :
case bube :
case dame :
case könig : wert = 10;
break;
case as : wert = 11;
break;
default : wert = 0;
} }
Abarbeitung der switch-Anweisung
Die Anweisungen in einem switch -Block werden se- quentiell abgearbeitet. Die break-Anweisung bewirkt ein Verlassen des switch-Blocks. Einen case-Block ohne eine break-Anweisung abzuschließen bewirkt, dass alle darauffolgenden case-Blöcke bis zu einem break oder dem Ende der switch-Anweisung ausge- führt werden.
Beispiel
int x = 0, y;
switch (x) {
case 0 : y = 1;
case 1 : y = 2; break;
case 2 : y = 3; break;
default : }
Der Benutzer wollte y den Wert 1 zuweisen. So aber er-
Praktische Informatik I
© Prof. Dr. W. Effelsberg
6. Die Programmiersprache C 6-71
6.3.4 Iteration (Wiederholungsanweisung)
Es gibt in C drei Varianten von Iterationsanweisungen:
• while-Schleife
• do-Schleife
• for-Schleife
while-Schleife
Bedingungsschleife
while ( Ausdruck ) Anweisung
Merke: Die Abbruchbedingung wird jeweils vor der Ausführung der Anweisungen geprüft.
Praktische Informatik I
© Prof. Dr. W. Effelsberg
6. Die Programmiersprache C 6-73
do-Schleife
Anweisung while Ausdruck
do-Schleife
do ( ) ;
Merke: Die Abbruchbedingung wird jeweils nach der Ausführung der Anweisungen geprüft.
for-Schleife ("Zählschleife") (1)
Die for-Schleife sieht allgemein wie folgt aus:
Zählschleife
for Ausdruck 1
Ausdruck 2
( ;
;
Ausdruck 3 ) Anweisung
Praktische Informatik I
© Prof. Dr. W. Effelsberg
6. Die Programmiersprache C 6-75
for-Schleife ("Zählschleife") (2)
Es gelten folgende Regeln:• Ausdruck1 wird nur einmal berechnet und dient zur In- itialisierung der Schleife (in der Regel zur Anfangszu- weisung an Kontrollvariable).
• Ausdruck2 ist ein logischer Ausdruck (boolean), in der Regel eine Abbruchbedingung. Er wird vor jedem
Schleifendurchlauf neu berechnet. Die for-Schleife bricht ab, wenn Ausdruck2 = 0 (false) ist.
• Ausdruck3 wird ebenfalls vor jedem Schleifendurch- lauf neu berechnet. Er dient zur Veränderung von Schleifenvariablen für den neuen Durchlauf.
Analogie zwischen for- und while-Schleife
Eine for-Schleife der Form
for ( expr1; expr2; expr3) Anweisungsblock;
ist äquivalent zu einer while-Schleife der Form expr1;
while (expr2) {
Anweisungsblock;
expr3;
}
Eine for-Schleife ist in der Regel immer dann sinnvoll, wenn die Anzahl der Wiederholungen im voraus be- kannt ist.
Praktische Informatik I
© Prof. Dr. W. Effelsberg
6. Die Programmiersprache C 6-77
break
und
continuein Schleifen (
1)continue bewirkt, dass der Anweisungsblock im Inne- ren der Schleife nicht weiter abgearbeitet wird, sondern sofort mit dem nächsten Schleifendurchlauf begonnen wird.
Beispiel
/* negative Elemente werden nicht bearbeitet */
#define N 10 int i, a[N];
for (i=0; i < N; i++) {
if (a[i] < 0) continue;
/* Bearbeitung positiver Elemente */
...
}
break
und
continuein Schleifen (
2) break bewirkt, dass die gesamte Schleife verlassen wird, nicht nur der aktuelle Schleifendurchlauf.Beispiel
Im obigen Beispiel bewirkt break an der Stelle von continue, dass beim Auftreten des ersten negativen Elements die Bearbeitung des gesamten Arrays abge- brochen wird.
Praktische Informatik I
© Prof. Dr. W. Effelsberg
6. Die Programmiersprache C 6-79
6.4 Unterprogramme
Unterprogramme dienen zur Modularisierung von Programmen. Unterprogramme werden deklariert und aufgerufen. Man unterscheidet traditionell zwei Arten von Unterprogrammen
• Prozeduren
• Führen einen Teil der Arbeit des aufrufenden Pro- gramms durch.
• Ergebnisse werden in der Regel in Form von Pa- rametern zurückgegeben.
• Funktionen
• führen die Berechnung von Funktionswerten im mathematischen Sinn durch.
• Ergebnisse werden (gegebenfalls zusätzlich zu Pa- rametern) durch den Funktionsaufruf zurückgelie- fert; der Wert des Ergebnisses tritt an die Stelle des Funktionsnamens im umgebenden Ausdruck.
In C gibt es nur einen Typ von Unterprogrammen, näm- lich Funktionen. Ergebniswerte von Funktionen können in C jedoch ignoriert werden, so dass eine C-Funktion sich wie eine Prozedur verhält.
Deklaration von Unterprogrammen (1)
Unterprogrammvereinbarung
Unterprogrammkopf Unterprogrammrumpf
Unterprogrammkopf
Typ- name
Routinen-
name ( Parameter-
liste )
Unterprogrammrumpf
Vereinbarungs- Anweisungs-
Praktische Informatik I
© Prof. Dr. W. Effelsberg
6. Die Programmiersprache C 6-81
Deklaration von Unterprogrammen (2)
Unterprogramme sollten im Deklarationsteil eines Pro- gramms, im Anschluss an die Variablen-Deklarationen vereinbart werden.Es sollte immer ein Typ für das Unterprogramm (und damit für den zurückgelieferten Wert) angegeben wer- den, auch wenn der C-Compiler dies nicht verlangt.
Wird kein Typ angegeben, geht der Compiler vom Typ
"int" aus.
Die
return-Anweisung
Die Rückgabe von Ergebnissen einer Funktion erfolgt in der Funktion durch die Anweisung return:
;
return-Anweisung
return Ausdruck
Nach dem Schlüsselwort return kann ein beliebiger Ausdruck stehen. Das Ergebnis der Funktion ist das Er- gebnis der Auswertung dieses Ausdrucks.
Merke: Eine Routine muss keinen Resultatwert liefern.
Ein leeres return bzw. die abschließende geschweifte Klammer beenden die Routine und geben 0 zurück
(normales Routinenende). Eine Routine sollte jedoch aus Gründen der Klarheit immer eine return-
Anweisung besitzen.
Praktische Informatik I
© Prof. Dr. W. Effelsberg
6. Die Programmiersprache C 6-83
Aufruf von Unterprogrammen (1)
Routinenaufruf
Variable Routinenname
aktueller Parameter (
,
)
, ...
;
=
Der Aufruf ohne Zuweisung an eine Variable ist, syn- taktisch gesehen, eine Anweisung (statement); dies entspricht der traditionellen Prozedur. Solche Unterpro- gramme werden mit dem Typ void vereinbart.
Der Aufruf mit Zuweisung an eine Variable ist, syntak- tisch gesehen, ein Ausdruck (expression); dies ent- spricht der traditionellen Funktion, bei der ein Wert zu- rückgegeben wird.
Aufruf von Unterprogrammen (2)
Beispiele
void mache_garnichts () {
}
double square_root (double value) {
return (sqrt(value));
}
Aufrufe:
double a, b;
...
mache_garnichts();
...
b = 4.0;
a = square_root(b);
Praktische Informatik I
© Prof. Dr. W. Effelsberg
6. Die Programmiersprache C 6-85
Korrespondenz zwischen formalen und aktuellen Parametern
• Aktuelle und formale Parameter sollten in der Anzahl übereinstimmen.
• Aktuelle und formale Parameter sollten im Typ über- einstimmen.
• Aktuelle und formale Parameter entsprechen einander in der Reihenfolge, in der sie in der Vereinbarung und im Aufruf auftreten (Stellungsparameter).
Variable Parameterlisten
Es dürfen beim Aufruf eines Unterprogramms auch
mehr Parameter übergeben werden als vereinbart sind.
Dazu ist in der Deklaration ' ...' als letzter Parameter notwendig. Dies ist sinnvoll, wenn vorab nicht bekannt ist, wieviele Parameter übergeben werden sollen.
Beispiel:
Die später noch einzuführende Funktion printf ist fol- gendermaßen deklariert:
int printf (const char *format , ... ) Sie gibt u.a. den Inhalt beliebig vieler Variablen auf dem Bildschirm aus.
Achtung
Es dürfen nie weniger Argumente als vereinbart über- geben werden, da ansonsten der Effekt des Aufrufs un-
Praktische Informatik I
© Prof. Dr. W. Effelsberg
6. Die Programmiersprache C 6-87
Beispiel für schwierige Semantik
int i;void test (int k; int j) { k = k + 1;
j = 3 i;
return;
} /*test*/
main () { int a[3];
a[0] = 1; a[1] = 2; a[2] = 3;
i = 1;
test (i, a[i]);
return;
}
Fragen bzgl. i und a[i]:
Wie wird auf den aktuellen Parameter zugegriffen?
• indem innerhalb der Routine Speicherplatz angelegt und der Wert dorthin kopiert wird?
• indem direkt auf den Speicherplatz der Variablen im Hauptprogramm zugegriffen wird?
• indem der Parameter-Ausdruck bei jeder Benutzung neu berechnet wird?
Call - by - value (1)
• Argumente werden bei Routinenaufruf in die Routine auf lokalen Speicherplatz kopiert.
• Berechnung der Parameterwerte bei Aufruf der Routi- ne.
• Alle Operationen innerhalb der Routine werden auf dem lokalen Speicherplatz ausgeführt.
Also:
Keine Auswirkungen außerhalb der Prozedur.
Nur geeignet für Eingangsparameter.
Praktische Informatik I
© Prof. Dr. W. Effelsberg
6. Die Programmiersprache C 6-89
Call - by - value (2)
int i, a[3];
void test (int k, int j) { k = k + 1;
j = 3 * a[i];
return;
} /*test*/
main () { a[0] = 1;
a[1] = 2;
a[2] = 3;
i = 1;
test (i, a[i]);
return;
}
i a[0] a[1] a[2]
1 1 2 3
Call - by - reference (1)
• bei Eintritt in die Routine wird die Speicheradresse des Parameters berechnet.
• alle Operationen innerhalb der Routine werden direkt auf den so berechneten Speicheradressen ausge- führt.
Also: Änderungen des Parameterinhaltes ändern die Umgebung. Geeignet für Eingangs- und Ausgangs- parameter, d.h. damit können Daten der aufrufenden Routine geändert werden!
Praktische Informatik I
© Prof. Dr. W. Effelsberg
6. Die Programmiersprache C 6-91
Call - by - reference (2)
int i, a[3];
void test (int *k, int *j) { *k = *k + 1;
*j = 3 * a[i];
return;
} /*test*/
main () { a[0] = 1;
a[1] = 2;
a[2] = 3;
i = 1;
test (&i, &a[i]);
return;
}
i a[0] a[1] a[2]
2 1 9 3
Call - by - name (1)
Ausdrücke sind als aktuelle Parameter erlaubt.
Operationen werden auf den Original-Speicherplätzen außerhalb der Routine ausgeführt.
Erneute Auswertung des Ausdrucks bei jeder Verwen- dung innerhalb des Unterprogramms!
Also: Der Call-by-name führt dann zu anderen Werten als der Call-by-reference, wenn mehrere Parameter übergeben werden, die voneinander abhängen.
Nicht empfehlenswert, da oft sehr schwer verständlich.
Praktische Informatik I
© Prof. Dr. W. Effelsberg
6. Die Programmiersprache C 6-93
Call - by - name (2)
int i, a[3];
void test (int *k, int *j) { *k = *k + 1;
*j = 3 * a[i];
return;
} /*test*/
main () { a[0] = 1;
a[1] = 2;
a[2] = 3;
i = 1;
test (&i, &a[i]);
return;
}
Call-by-name ist in C nicht möglich! Dazu müsste "*j"
im Unterprogramm "test" erst nach der Anweisung
"* k=*k+1" erneut ausgewertet werden, d.h. da "*j" für
"a[i]" steht und "i= * k" ist, wäre "*j= a [2]". Damit würde das Programm folgende Ergebnisse liefern:
a[0] a[1] a[2]
2 1 2 9
Binderegeln in C (1)
Es gibt nur Call-by-value in C.
Call-by-reference kann durch den Referenzoperator * dargestellt werden.
Parameterklasse Übergaberegel aktueller Para- meter
Wertparameter Referenzpara- meter
Routinenpara- meter
Call-by-value call-by-reference call-by-reference
Ausdruck
Variablenreferenz Routinenreferenz
Praktische Informatik I
© Prof. Dr. W. Effelsberg
6. Die Programmiersprache C 6-95
Binderegeln in C (2)
Parameterliste
,
Wertparameter
Routinen-
referenzparameter Variablen-
referenzparameter
Binderegeln in C (3)
)
Wertparameter
Variablenreferezparameter
Typname Parametername
Typname * Parametername
Routinenreferezparameter
Typname ( * Routinenname
( )
* Parametertyp
Praktische Informatik I
© Prof. Dr. W. Effelsberg
6. Die Programmiersprache C 6-97
Binderegeln in C (4)
Beispiele
a) Call-by-value
float Betrag (float x) {
if (x >= 0)
return(x);
else
return(-x);
}
Aufgerufen wird die Funktion z.B. durch y = Betrag (3.14 * z);
Binderegeln in C (5)
b) Call-by-reference
void Tausch (int *a, int *b) {
int hilf;
hilf = *a;
*a = *b;
*b = hilf;
return;
}
Aufgerufen wird die Funktion z.B. durch Tausch(&x, &y);
(wobei x und y integer sind)
Praktische Informatik I
© Prof. Dr. W. Effelsberg
6. Die Programmiersprache C 6-99
Binderegeln in C (6)
c) Routinen als Parameter
(*F)(float) sei eine beliebige reellwertige Funktion, bei der (*F)(a)<0 und (*F)(b)>0 ist
.
Das Unterprogramm "Nullstelle" berechnet nun
nach der Methode der Intervallhalbierung eine Null- stelle von (* F).
float Nullstelle(float(*F)(float), float a, float b) {
float mittelpunkt = 0.0;
while (fabs((*F)(mittelpunkt) > (1e-10))) {
mittelpunkt = (a+b)/2;
if ( (*F)(mittelpunkt) < 0) a = mittelpunkt;
else
b = mittelpunkt;
}
return (mittelpunkt);
}
Binderegeln in C (7)
Mittelpunkt a
F(x)
b
Achtung: Bei der Angabe der Routine (*F) als Para- meter muss auf die Klammern geachtet werden, da
Praktische Informatik I
© Prof. Dr. W. Effelsberg
6. Die Programmiersprache C 6-101
Standardfunktionen in C (1)
In der Standard include-Datei <math. h> vereinbarte mathematische Standardfunktionen:
Aufruf Para- metertyp
Ergebnistyp Bedeutung abs (x)
labs (x) fabs (x) ceil (x)
floor (x)
sin (x) cos (x) exp (x) log (x) sqrt (x) atan (x) pow (x,y)
integer long float double
double
double double double double double double double
integer long float double
double
double double double double double double double
Betrag eines Integers Betrag eines Longs Betrag eines Floats kleinster ganzzahliger Wert,der nicht kleiner als x ist
größter ganzzahliger Wert,der nicht größer als x ist
Sinusfunktion Cosinusfunktion Exponentialfunktion 10er- Logarithmus Wurzel einer Zahl Arcustangensfunktion x hoch y
Standardfunktionen in C (2)
In der Standard include-Datei <string. h> vereinbarte Standardfunktionen zur Handhabung von Zeichenket- ten:
Aufruf Bedeutung
char *strcpy(s,ct) char *strncpy(ct,n) char *strcat(s,ct) char *strncat(s,ct,n) int strcmp(cs,ct) int strncmp(cs,ct,n) char *strstr(cs,ct) size_t strlen(cs)
Kopiert Zeichenkette ct in Vektor s Kopiert höchstens n Zeichen aus ct in s
Hängt Zeichenkette ct an s hinten an Hängt höchstens n Zeichen an
Vergleicht Zeichenketten cs und ct Vergleicht höchstens n Zeichen von cs und ct
Liefert Zeiger auf erste Kopie von ct in cs
Liefert Länge von cs
Praktische Informatik I
© Prof. Dr. W. Effelsberg
6. Die Programmiersprache C 6-103
Gültigkeitsbereich von Namen
Wenn Variablen, Konstanten usw. innerhalb einer Pro- zedur oder Funktion denselben Namen haben wie Va- riablen, Konstanten usw. außerhalb, muss klar definiert sein, welches Objekt jeweils gemeint ist. Es gilt:
Jede Vereinbarung eines Namens hat nur in dem Block Gültigkeit, in dem sie vorgenommen wird.
Also:
Ein Name bezieht sich immer auf die am nächsten lie- gende Deklaration.
Namen müssen innerhalb eines Blockes eindeutig sein.
Die Deklaration muss der Verwendung vorangehen.
Ein innerhalb eines Blockes vereinbarter Name heißt lokal.
Ein außerhalb des Blockes vereinbarter Name heißt global.
Blockstruktur
In C kann jeder Anweisungsblock am Beginn eigene Deklarationen enthalten. Ansonsten gibt es Vereinba- rungen außerhalb von Routinen ("globale") und zu Be- ginn von Routinen.
UP 1
UP 2
UP n
Block 4
Block 1
Block 2
Hauptprogramm
. . .
Block 3
Block 5
Achtung:
Praktische Informatik I
© Prof. Dr. W. Effelsberg
6. Die Programmiersprache C 6-105
Regeln für die Sichtbarkeit von Vereinbarungen
• Sichtbarkeit von äußeren Blöcken nach innen
• keine Sichtbarkeit von innen nach außen
• keine gegenseitige Sichtbarkeit für Blöcke derselben Schachtelungstiefe
Beispiel
int a,b,c
function g int x,y,z
main int x,y
b2
int c,d,e b1
int d,e,f
Gültigkeitsbereich vs. Lebensdauer
Der Gültigkeitsbereich eines Namens umfasst den Block, in dem der Name deklariert ist.Die Lebensdauer eines Objekts umfasst den Block, in dem es definiert ist: es existiert nur so lange, wie An- weisungen des zugehörigen Blocks ausgeführt werden.
Das Laufzeitsystem von C legt beim Eintritt in einen Block den Speicherplatz für die dort lokal benötigten Objekte an und gibt ihn beim Verlassen des Blocks wie- der frei.
Eine Ausnahme hierzu bildet die static-Deklaration:
Wird eine Variable innerhalb einer Funktion als static deklariert, so behält sie ihren Wert auch nach Beendi- gung der Funktion. Bei erneutem Aufruf hat sie den Wert vom vorigen Verlassen der Prozedur.
Beispiel: static int alert;
Merke:
Objekte, die nur innerhalb eines Blocks benötigt werden,
Praktische Informatik I
© Prof. Dr. W. Effelsberg
6. Die Programmiersprache C 6-107
Rekursion in C (1)
Da für alle Call-by-Value-Parameter und für alle lokalen Variablen Speicherplatz beim Prozedureintritt dyna- misch angelegt wird, können Funktionen und Prozedu- ren in C rekursiv aufgerufen werden.
Die Anweisungen innerhalb eines Prozedurrumpfes be- ziehen sich dabei jeweils auf die lokalen Variablen und Parameter.
Bei der Rückkehr aus der Rekursion findet die Funktion bzw. Prozedur dann jeweils wieder die alten Werte vor.
Rekursion in C (2)
Beispiel
int fak (int k) {
if (k==0)
return (1);
else
return (k * fak (k-1));
}
1 * 1 1
1 * fak (0) 2 * fak (1)
2 * 1 3 * fak (2)