9. Funktionen
Bisher waren die Programme noch recht klein. Wird die zu lösende Aufgabe komplexer, so
sollte das Programm in übersichtliche Teile zerlegt werden. Diese Teile können
dann immer noch so komplex sein, dass sie weiter unterteilt werden usw. Der Entwurf
dieser Hierarchie nennt sich Prinzip der schrittweisen Verfeinerung.
Diese Teilprogramme werden Funktionen genannt. Eine Funktion erledigt
eine abgeschlossene Teilaufgabe. Weiterhin müssen der Funktion die zu verarbeitenden
Werte mitgegeben werden. Dieses geschieht mit sogenannten Argumenten
bzw. Parametern. Die Funktion liefert das Ergebnis an die aufrufende
Funktion zurück. Dieses Ergebnis wird auch Rückgabewert
genannt. Ein Beispiel ist die Sinus-Funktion y = sin(x): Hier wird der
Wert x als Parameter der Funktion übergeben und das Ergebnis der Sinus-Funktion wird
der Variablen y zugewiesen.
Eine Funktion muss nur einmal definiert werden. Danach kann sie beliebig oft durch
Nennung ihres Namens (dem Funktionsnamen) aufgerufen werden. Eine
Funktion ist also wiederverwendbar!
9.1. Funktionsprototypen und -definitionen
Bei Funktionen wird zwischen der Deklaration (Bekanntmachung des Namens) und der
Definition (Belegung eines Speicherbereichs) unterschieden. Die Deklaration der Funktionen
wird im allgemeinen vor dem Hauptprogramm main() geschrieben. Diese
Deklarationen werden hier Funktionsprototypen genannt. Die Syntax
eines Funktionsprototyps sieht folgendermaßen aus:
Rückgabe-Datentyp Funktionsname(Datentyp [Parametername], ...);
Die Parameter werden bei Funktionsprototypen und -definitionen auch
Formalparameter genannt. Die Parameteranzahl kann bei jeder Funktion
unterschiedlich sein. Es können Funktionen mit einer Parameteranzahl zwischen 0 und
"beliebig viele" deklariert und definiert werden. Beim Aufruf der Funktion dagegen
muss exakt die bei der Deklaration bzw. der Definition vorgegebene Anzahl der Parameter
angegeben werden. Der Name des Parameters muss bei der Deklaration nicht angegeben werden,
wohl aber bei der Definition.
Durch die Deklaration "weiß" der Compiler, dass irgendwo eine Funktion mit dem
angegebenen Funktionsnamen definiert ist, wieviele Parameter sie hat und welchen Datentyp
der Rückgabewert hat. Wird diese Funktion im Programm aufgerufen, kann der Compiler
jetzt eine Syntaxprüfung machen, ohne dass die Funktion definiert sein muss.
Erst durch die Funktionsdefinition kann die Funktion auch angewendet
werden, denn erst hier wird der Quellcode angegeben und wird entsprechend Speicherplatz
dafür reserviert. Die Syntax einer Funktionsdefinition sieht folgendermaßen
aus:
Rückgabe-Datentyp Funktionsname(Datentyp Parametername, ...)
{ Anweisungen;
}
Der wichtigste Unterschied in der Syntax zwischen Funktionsprototyp und -definition ist,
dass beim Prototyp am Ende der Zeile ein Semikolon steht, während bei der
Definition kein Semikolon stehen darf. Dafür folgt bei der Definition in den
darauffolgenden Zeilen der Quellcode der Funktion, der sogenannte
Funktionskörper. Der Quellcode der Funktion wird - auch wenn die
Funktion nur eine Anweisung beinhaltet - zwischen einem Paar geschweifte Klammern gesetzt
(genauso wie bei der main-Funktion).
Beispiel:
kap09_01.c
01 #include <stdio.h>
02
03 /* Funktionsprototyp: */
04 double Average(double, double, double);
05
06 /* Hauptprogramm: */
07 int main()
08 {
09 double a = 4.5, b = 3.1415, c = 7.99;
10
11 /* Aufruf der Funktion in der printf-Anweisung: */
12 printf("Durchschnitt: %f\n", Average(a, b, c));
13
14 return 0;
15 }
16
17 /* Funktionsdefinition: */
18 double Average(double Zahl1, double Zahl2, double Zahl3)
19 {
20 return (Zahl1 + Zahl2 + Zahl3) / 3.0;
21 }
Aufgerufen wird die Funktion durch den Funktionsnamen gefolgt von den Parametern, die in
Klammern gesetzt werden. Die Parameter werden in diesem Fall Aktualparameter
genannt. Die Klammern müssen auch dann gesetzt werden, wenn keine Parameter der
Funktion übergeben werden. Die Syntax für einen Funktionsaufruf lautet also
Funktionsname(Variablenname bzw. Konstante, ...);
Der Rückgabewert der Funktion kann in einer Variablen gespeichert werden oder wie im
Beispiel gleich einer anderen Funktion übergeben werden (printf
ist auch eine Funktion) oder einfach "vergessen" werden, wenn das Funktionsergebnis nicht
benötigt wird. Z.B. liefert auch die printf-Funktion ein Ergebnis
zurück (nämlich die Anzahl der ausgegebenen Zeichen), aber dieses Ergebnis wird
nicht weiter benötigt, also wird es auch nicht weiter verarbeitet.
9.2. Gültigkeitsbereiche und Sichtbarkeit
Grundsätzlich sind alle deklarierten Namen von Variablen, Typen, Konstanten,
Funktionen, usw. nach der Deklaration nur innerhalb des Blocks gültig, in dem sie
deklariert wurden. D.h. z.B. alle Variablen, die innerhalb einer Funktion deklariert bzw.
definiert werden, sind nur innerhalb dieser Funktion bekannt und sichtbar; in jeder anderen
Funktion sind diese Variablen unbekannt. Diese Variablen werden lokale
Variablen genannt; sie sind nur in der lokalen Umgebung (innerhalb des Blocks) bekannt.
Nach Verlassen des Blocks werden sie wieder vernichtet, d.h. ihr Speicherplatz wird wieder
freigegeben.
Variablen, die außerhalb von allen Blöcken deklariert werden, sind innerhalb der
ganzen Datei gültig, d.h. innerhalb der main- und innerhalb aller
anderen Funktionen, die in der gleichen Quellcodedatei definiert sind. Dadurch, dass
diese Variablen global gelten, werden sie auch globale Variablen
genannt.
Grundsätzlich sollte auf globale Variablen nach Möglichkeit verzichtet werden und
statt dessen lieber diese Variablen lokal angelegt und bei Bedarf als Parameter an die
Funktionen übergeben werden.
Im folgenden Beispielprogramm gibt der Compiler jeweils eine Fehlermeldung für die Zeilen
13 und 24 aus, da in beiden Fällen die Variablen nicht bekannt (deklariert) sind.
Beispiel:
kap09_02.c
01 #include <stdio.h>
02
03 int a; /* globale Variable */
04
05 void Test(void); /* keine Parameter, kein Rückgabewert */
06
07 int main()
08 {
09 int b; /* lokal im Hauptprogramm */
10
11 a = 0; /* erlaubt, da a global */
12 b = 0; /* erlaubt, da b in diesem Block deklariert */
13 c = 0; /* FEHLER!, da c nur in Funktion bekannt */
14 Test();
15
16 return 0;
17 }
18
19 void Test(void)
20 {
21 int c; /* lokal in dieser Funktion */
22
23 a = 0; /* erlaubt, da a global */
24 b = 0; /* FEHLER!, da b nur im Hauptprogramm bekannt */
25 c = 0; /* erlaubt, da c in dieser Funktion deklariert */
26 }
Nach diesen Angaben ist es nun auch möglich, mitten im Programm einen Block
einzusetzen und in diesem Block lokale Variablen zu deklarieren bzw. zu definieren. Das
sieht dann wie folgt aus.
Beispiel:
kap09_03.c
01 #include <stdio.h>
02
03 int main()
04 {
05 int a; /* lokal im Hauptprogramm */
06
07 a = 0; /* erlaubt, da a im Hauptprogramm deklariert */
08
09 /* Block innerhalb des Hauptprogramms: */
10 {
11 int b; /* lokal in diesem Block */
12
13 a = 3; /* erlaubt */
14 b = 3; /* erlaubt */
15 }
16 b = 0; /* FEHLER!, da b nur in dem Block bekannt */
17
18 return 0;
19 }
Eine Ausnahme bilden lokale Variable, die innerhalb eines Blocks oder einer Funktion als
statische Variable definiert werden. Dazu wird vor dem Datentyp
zusätzlich das Schlüsselwort static verwendet. Diese
statischen Variablen werden nach Verlassen des Blocks oder der Funktion nicht vernichtet
und haben bei erneutem Aufruf des Blocks oder der Funktion noch den alten Wert. Ferner wird
eine evtl. Variableninitialisierung nur bei der erstmaligen Definition ausgeführt; bei
allen weiteren Aufrufen wird die Initialisierung ignoriert.
Beispiel:
kap09_04.c
01 #include <stdio.h>
02
03 void Test(void);
04
05 int main()
06 {
07 int i;
08
09 for (i = 0; i < 3; i++)
10 Test();
11
12 return 0;
13 }
14
15 void Test(void)
16 {
17 static int Anzahl = 0;
18 /* wird nur beim 1. Aufruf auf Null gesetzt! */
19
20 Anzahl++;
21 printf("Anzahl = %i\n", Anzahl);
22 }
Die Ausgabe des Programms ist
Ausgabe = 1
Ausgabe = 2
Ausgabe = 3
Ohne das Schlüsselwort static würde dreimal eine 1
ausgegeben werden, da die lokale Variable bei jedem Funktionsaufruf wieder neu erzeugt
würde.
Die Parameter einer Funktion werden innerhalb der Funktion als lokale Variablen behandelt;
von außen betrachtet stellen sie die Daten-Schnittstelle zur Funktion dar. Mehr dazu
im nächsten Abschnitt.
9.3. Funktionsschnittstelle
Der Datentransfer in Funktionen hinein (Parameter) und aus Funktionen heraus
(Rückgabewert) wird durch die Beschreibung der Schnittstelle
festgelegt. Unter einer Schnittstelle ist eine formale Vereinbarung zwischen Aufrufer und
Funktion über die Art und Weise des Datentransports zu verstehen. Auch das, was die
Funktion leistet, gehört zur Schnittstelle (sollte als Kommentar beim Funktionskopf
stehen). In diesem Abschnitt soll es nur um den Datentransfer gehen. Die Schnittstelle ist
durch den Funktionsprototyp eindeutig beschrieben und enthält folgendes:
den Rückgabetyp der Funktion,
den Funktionsnamen,
Parameter, die der Funktion bekannt gemacht werden inkl. deren Datentypen und
die Art der Parameterübergabe.
Der Compiler prüft, ob die Definition der Schnittstelle bei einem Funktionsaufruf
eingehalten wird.
Für den Datentransfer in die Funktion hinein gibt es zwei verschiedene Arten des
Datentransports: Die Übergabe per Wert und die Übergabe per Zeiger.
Übergabe per Wert
Bei der Übergabe per Wert wird der Wert in den sogenannten Stack
(einem Zwischenspeicher u.a. für die Parameterübergabe) kopiert - daher wird dies
manchmal auch Übergabe per Kopie genannt. Innerhalb der Funktion werden die Werte
auf dem Stack als lokalen Variable verwendet, die am Ende der Funktion wieder vernichtet werden,
während die Originale unverändert bleiben.
Beispiel:
kap09_05.c
01 #include <stdio.h>
02
03 int Addiere_3(int);
04
05 int main()
06 {
07 int Ergebnis, Zahl = 2;
08
09 printf("Wert von Zahl = %i\n", Zahl);
10 Ergebnis = Addiere_3(Zahl);
11 printf("Ergebnis 'Addiere_3(Zahl)' = %i\n", Ergebnis);
12 printf("Wert von Zahl = %i (unveraendert)\n", Zahl);
13
14 return 0;
15 }
16
17 int Addiere_3(int x)
18 {
19 x += 3;
20 return x;
21 }
Die Übergabe per Wert sollte generell verwendet werden, wenn ein Objekt von der
Funktion nicht verändert werden soll. Wenn der Kopiervorgang in den Stack allerdings
zu lange dauert (bei sehr großen Objekten oder bei häufigem Aufruf der
Funktion), kann auch eine Übergabe per Zeiger geschehen. Dann sollte allerdings
sichergestellt werden, dass die Funktion den übergebenen Wert nicht
verändert, z.B. durch Verwendung von const-Parametern.
Übergabe per Zeiger
Die Übergabe per Zeiger ist ein Spezialfall der Übergabe per Wert, es wird
nämlich der Zeiger auf das Objekt im Stack abgelegt. Innerhalb der Funktion wird
dieser Zeiger auf dem Stack wieder als lokale Variable behandelt. Der Zeiger
wird also am Ende der Funktion wieder vernichtet. Aber über diesen Zeiger kann auf das
eigentliche Objekt zugegriffen (und damit auch verändert) werden. Es wird also nicht
das Objekt selber übergeben, sondern ein Zeiger auf das Objekt.
Bei den Parametern wird vor dem Parameternamen ein Stern gesetzt, da ja ein Zeiger
übergeben wird; der Datentyp dagegen wird nicht geändert. Beim Aufruf selber
wird vor dem Parameternamen der Adressoperator ('&') gesetzt.
Dadurch wird ein Zeiger auf das eigentliche Objekt erzeugt und der Funktion übergeben.
Das obige Beispiel wird nun so geändert, dass die Zahl per Zeiger an die Funktion
übergeben wird.
Beispiel:
kap09_06.c
01 #include <stdio.h>
02
03 int Addiere_3(int *);
04
05 int main()
06 {
07 int Ergebnis, Zahl = 2;
08
09 printf("Wert von Zahl = %i\n", Zahl);
10 Ergebnis = Addiere_3(&Zahl);
11 printf("Ergebnis 'Addiere_3(&Zahl)' = %i\n", Ergebnis);
12 printf("Wert von Zahl = %i (veraendert!!!)\n", Zahl);
13
14 return 0;
15 }
16
17 int Addiere_3(int *x)
18 {
19 *x += 3;
20 return *x;
21 }
Rückgabewerte
Der Rückgabewert wird innerhalb der Funktion mit dem Befehl
return Wert; angegeben, wobei Wert
der Rückgabewert ist. Gleichzeitig beendet dieser Befehl die Funktion, unabhängig
davon, ob weitere Anweisungen folgen oder nicht. Als Beispiel wird noch einmal das obige
Beispiel verwendet.
Beispiel:
kap09_07.c
01 #include <stdio.h>
02
03 int Addiere_3(int);
04
05 int main()
06 {
07 int Ergebnis, Zahl = 2;
08
09 printf("Wert von Zahl = %i\n", Zahl);
10 Ergebnis = Addiere_3(Zahl);
11 printf("Ergebnis 'Addiere_3(Zahl)' = %i\n", Ergebnis);
12 printf("Wert von Zahl = %i (unveraendert)\n", Zahl);
13
14 return 0;
15 }
16
17 int Addiere_3(int x)
18 {
19 x += 3;
20 return x;
21 printf("STOP!"); /* Diese Anweisung wird nie ausgefuehrt! */
22 }
Bei der Rückgabe von Zeigern muss darauf geachtet werden, dass das dazugehörige
Objekt auch in der aufrufenden Funktion existiert. Wenn z.B. ein Zeiger auf eine lokale
Variable zurückgegeben wird, greift die aufrufende Funktion auf einen Speicherbereich
zu, der eventuell bereits von einem anderen Programm oder einer anderen Funktion verwendet
wird. Das Ergebnis ist dann u.U. falsch. Im schlimmsten Fall kann sogar ein Systemabsturz
erzeugt werden! Das folgende Beispiel zeigt, wie es falsch ist, obwohl der Compiler
u.U. keine Fehler und keine Warnungen anzeigt und das Programm sogar läuft.
Beispiel:
kap09_08.c
01 #include <stdio.h>
02
03 int *Maximum(int, int);
04
05 int main()
06 {
07 int x = 17, y = 4, *zp1, *zp2, z;
08
09 zp1 = Maximum(x, y);
10 zp2 = Maximum(y, x);
11 z = *zp1; /* Ergebnis 1. Fkt.aufruf zwischenspeichern */
12 printf("x = %i\n", x);
13 printf("y = %i\n", y);
14 printf("z = %i\n", z); /* Ergebnis 1. Fkt.aufruf */
15 printf("Maximum(%i, %i) = %i\n", x, y, *zp1); /* 1. Fkt.aufruf */
16 printf("Maximum(%i, %i) = %i\n", y, x, *zp2); /* 2. Fkt.aufruf */
17
18 return 0;
19 }
20
21 int *Maximum(int a, int b)
22 {
23 /* a und b sind lokale Kopien!!! */
24 return a > b ? &a : &b; /* Fehler!!! */
25 }
Zuerst wird der Zeiger zp1 auf die lokale Variable a gesetzt (da x > y
ist). Anschließend wird die gleiche Funktion noch einmal aufgerufen. Dabei werden die
lokalen Variablen a und b, die mit hoher
Wahrscheinlichkeit die gleichen Speicheradressen belegen, auf andere Werte gesetzt. Damit zeigt
auch zp1 auf einen anderen Wert. Damit ist das Ergebnis in
z und in *zp1 falsch!
9.4. Rekursiver Funktionsaufruf
Der Aufruf einer Funktion durch sich selbst wird Rekursion genannt.
Eine Rekursion muss irgendwann auf eine Abbruchbedingung stoßen, damit die
Rekursion nicht unendlich ist. Bei einer unendlichen Rekursion wird irgendwann ein
sogenannter Stacküberlauf (stack overflow)
erzeugt; das Programm wird damit abgebrochen.
Als Beispiel für die Verwendung einer Rekursion wird die Quersumme einer ganzen Zahl
berechnet: Eine Funktion ermittelt die letzte Ziffer einer Zahl, addiert diese zur
Quersumme und ruft sich selbst mit den restlichen Ziffern wieder auf. Das Prinzip dieser
Funktion lässt sich in zwei Sätze zusammenfassen:
1. Die Quersumme der Zahl 0 ist gleich 0. Dies ist die Abbruchbedingung für die
Rekursion!
2. Die Quersumme einer Zahl ist gleich der letzten Ziffer plus der Quersumme der Zahl, die
um diese Ziffer gekürzt wurde.
Die Quersumme von 873956 ist also gleich 6 plus der Quersumme von 87395 und ist damit
gleich 6 plus 5 plus der Quersumme von 8739 usw. Auf jede Quersumme wird der Satz 2
angewandt, bis der Satz 1 gilt. Satz 1 gilt dann, wenn alle Ziffern von der Zahl abgetrennt
wurden. Die letzte Ziffer der Zahl wird durch modulo 10 (Divisionsrest) abgetrennt.
Die Zahl ohne der letzten Ziffer wird durch eine ganzzahlige Division durch 10
erhalten.
Beispiel:
kap09_09.c
01 #include <stdio.h>
02
03 int Quersumme(unsigned long);
04
05 int main()
06 {
07 unsigned long Zahl;
08
09 printf("Bitte eine positive ganze Zahl eingeben: ");
10 scanf("%lu", &Zahl);
11 printf("Quersumme von %u ist %i\n", Zahl, Quersumme(Zahl));
12
13 return 0;
14 }
15
16 int Quersumme(unsigned long x)
17 {
18 int letzteZiffer = 0;
19
20 if (!x) /* if (x == 0) Abbruchbedingung */
21 return 0; /* Abbruch der Rekursion */
22 else
23 {
24 letzteZiffer = x % 10; /* modulo 10 */
25 return letzteZiffer + Quersumme(x / 10); /* Rekursion */
26 }
27 }
Die Funktion Quersumme kann auch nicht-rekursiv geschrieben werden, in
dem eine Schleife verwendet wird. Diese Variante wird iterativ
genannt.
kap09_10.c
01 #include <stdio.h>
02
03 int Quersumme(unsigned long);
04
05 int main()
06 {
07 unsigned long Zahl;
08
09 printf("Bitte eine positive ganze Zahl eingeben: ");
10 scanf("%lu", &Zahl);
11 printf("Quersumme von %u ist %i\n", Zahl, Quersumme(Zahl));
12
13 return 0;
14 }
15
16 int Quersumme(unsigned long x)
17 {
18 int QSumme = 0;
19
20 while (x > 0)
21 {
22 QSumme += x % 10; /* letzte Ziffer addieren */
23 x /= 10; /* letzte Ziffer abtrennen */
24 }
25 return QSumme; /* Rueckgabe der Quersumme */
26 }
9.5. Zeiger auf Funktionen
Steht zum Zeitpunkt der Compilierung noch nicht fest, welche Funktion zur Laufzeit
aufgerufen werden soll (z.B. wenn der Anwender zur Laufzeit erst die gewünschte
Funktion auswählt) oder an welcher Adresse die Funktion steht (z.B. wenn Funktionen
zur Laufzeit nachgeladen werden und daher deren Adressen beim Kompilieren noch nicht
bekannt sind), wird mit Zeigern auf Funktionen gearbeitet.
Das folgende Beispiel soll den Umgang mit Zeigern auf Funktionen verdeutlichen:
Beispiel:
kap09_11.c
01 #include <stdio.h>
02 #include <math.h>
03
04 void Funktionswerte(double (*)(double));
05
06 int main()
07 {
08 double (*TrigFkt)(double); /* Zeiger auf Funktion, die ein
09 double als Parameter erhaelt
10 und ein double zurueckgibt. */
11
12 TrigFkt = sin; /* Zeiger auf sin-Funktion zuweisen */
13 Funktionswerte(TrigFkt);
14
15 return 0;
16 }
17
18 void Funktionswerte(double (*Fkt)(double))
19 {
20 static const double PI = 4 * atan(1);
21 double x;
22
23 for (x = 0; x < PI; x += 0.01)
24 printf("f(%5.2f) = %5.2f\n", x, Fkt(x));
25 }
Auch ein Array von Zeigern auf Funktionen ist möglich. Dazu wird gleich hinter dem
Zeigernamen der Index angegeben.
Beispiel:
kap09_12.c
01 #include <stdio.h>
02 #include <math.h>
03
04 void Funktionswerte(double (*)(double));
05
06 int main()
07 {
08 double (*TrigFkt[2])(double); /* Array von Zeigern auf Funktionen,
09 die ein double als Parameter
10 erhalten und ein double
11 zurueckgeben. */
12
13 TrigFkt[0] = sin; /* Zeiger auf sin-Fkt. zuweisen */
14 TrigFkt[1] = cos; /* Zeiger auf cos-Fkt. zuweisen */
15 Funktionswerte(TrigFkt[0]);
16 Funktionswerte(TrigFkt[1]);
17
18 return 0;
19 }
20
21 void Funktionswerte(double (*Fkt)(double))
22 {
23 static const double PI = 4 * atan(1);
24 double x;
25
26 for (x = 0; x < PI; x += 0.01)
27 printf("f(%5.2f) = %5.2f\n", x, Fkt(x));
28 }
Zeiger auf Funktionen scheinen aber nur unzureichend standardisiert zu sein, da einige
Compiler diese Beispiele nicht korrekt verarbeiten können.
9.6. Die Funktion main()
Die Funktion main() - das Hauptprogramm - ist eine spezielle Funktion.
Jedes C-/C++-Programm startet definitionsgemäß mit main(),
so dass main() in jedem Programm genau einmal vorhanden sein
muss. Der Rückgabewert ist standardmäßig int,
aber viele Compiler lassen auch void zu (dann ist natürlich auch
kein return 0; mehr erlaubt!). Die main()-Funktion
kann nicht überladen werden. Die zwei folgenden Formen werden von allen Compilern
unterstützt.
einfache Form:
int main()
{ ...
return 0; /* Exit-Code */
}
allgemeine (komplexere) Form:
int main(int argc, char* argv[])
{ ...
return 0; /* Exit-Code */
}
In der zweiten Form werden zwei Parameter übergeben. Über diese beiden Parameter
kann auf alle Kommandozeilenparameter zugegriffen werden, die beim
Aufruf des Programms angegeben wurden. Das folgende Beispiel startet das Programm
prog mit 4 Kommandozeilenparameter.
Beispiel:
./prog 1 Test 547.32 3
Der erste Parameter argc ist die Anzahl der Kommandozeilenparameter
einschließlich des Programmaufrufs, im Beispiel gleich 5. Der zweite Parameter ist
ein String-Array, also ein Array von Zeichenketten. In diesen Zeichenketten stehen die
einzelnen Kommandozeilenparameter. Für das obige Beispiel sind folgende Werte in
diesem Array gespeichert:
argv[0] = "./prog"
argv[1] = "1"
argv[2] = "Test"
argv[3] = "547.32"
argv[4] = "3"
argv[5] = NULL
Wichtig: Auch die Zahlen-Kommandozeilenparameter werden hier als Texte
gespeichert.
Nun folgt ein Beispielprogramm, dass die Anzahl sowie alle Kommandozeilenparameter
auflistet.
Beispiel:
kap09_13.c
01 #include <stdio.h>
02
03 int main(int argc, char *argv[])
04 {
05 int i = 1;
06
07 printf("Programmaufruf: %s\n", argv[0]);
08 printf("Anzahl Kommandozeilenparameter: %i\n", argc - 1);
09 printf("Kommandozeilenparameter:\n");
10 while (argv[i])
11 {
12 printf("%2i: %s\n", i, argv[i]);
13 i++;
14 }
15
16 return 0;
17 }
Voriges Kapitel: 8. Zeiger
Nächstes Kapitel: 10. Präprozessor-Befehle