|
int quad (int x);
Die Funktion mit Anweisungsteil wird dann später im Programm definiert.
Solche Prototyp-Deklarationen findet man auch in den Header-Dateien.
Beim Aufruf der Funktion werden die formalen Parameter durch die aktuellen
Parameter (=Argumente) ersetzt (Parameterversorgung der Funktion). Ähnlich wie
bei allen anderen Variablen können diese durch ihre expliziten
Werte, Konstante oder Variable versorgt werden. Zum Beispiel:
y = quad(25);
Der Typ des aktuellen Parameters muß natürlich auch den Typ des
formalen Parameters entsprechen (wird bei vielen höheren Programmiersprachen
geprüft) --> sichere Programme.
Beispiel fuer eine Funktion, Potenzen berechnen:
#include <stdio.h>
int power(int,int); /* Prototyp */
int main(void)
{
int i;
for (i = 1; i <= 10; ++i)
printf("%d %d %d\n", i, power(2,i), power(-3,i));
exit(0);
}
int power(int base, int n)
{
int i, p = 1;
for (i = 1; i <= n; i++)
p = p*base;
return p;
}
Bei vielen höheren Programmiersprachen wird bei den Parametern
neben dem Typ auch noch die Art der Parameterersetzung festgelegt.
Man unterscheidet zwischen folgenden Arten der Parameterersetzung:
- Der aktuelle Parameter wird ausgewertet und das Resultat dem
formalen Parameter, der eine lokale Variable darstellt, zugewiesen.
Diese Art wird Werte-Parameter (value parameter) genannt und ist die
häufigste Form der Ersetzung. Anstelle des
Parameters kann auch ein Ausdruck stehen (z. B.: quad(2*x + 1)).
- Der aktuelle Parameter ist eine Variable (handelt es sich um
eine Array-Komponente, wird der Index-Ausdruck ausgewertet).
Die Variable ersetzt den formalen Parameter. Diese Art wird
Variablen-Parameter (variable parameter) genannt und muß immer
dann verwendet werden, wenn der Parameter ein Resultat der Funktion
darstellt (d. h. wenn Werte aus der Funktion heraus transportiert
werden sollen).
In C wird hier die Adresse der Variablen übergeben. Dies geschieht bei der
Funktionsdefinition durch das Voranstellen eines Sternchens (*)
vor den Parameternamen, z. B. int *varpar.
Um beim Aufruf der Funktion den Wert herauszutransportieren, wird dem aktuellen
Variablenparameter ein &-Zeichen vorangestellt, z. B. foo(&x);.
Was sich hinter den Operatoren '*' und '&' genau verbirgt, erfahren Sie
im Kapitel über Pointer. Für den Augenblick reicht die Regel:
- Adressoperator:
& liefert die Adresse einer Variablen zurück.
Beispiel: int a;: Adresse von a ist &a
- Inhaltsoperator:
* gibt den Inhalt einer Speicherstelle mit einer bestimmten Adresse an.
Beispiel: int a;: a = *(&a)
Beispiel: Funktion, die die Inhalte zweier Variablen vertauscht.
void swap(int *n, int *m)
{
int park;
park = *n;
*n = *m;
*m = park;
}
void main(void)
{
int a, b;
...
swap(&a, &b); /* Funktionsaufruf */
...
}
Beispiel für formale und aktuelle Parameter:
Beim Programm für die quadratische Gleichung könnte man den Algorithmus
zur Lösung der Gleichung als Unterprogramm formulieren, um es beliebig oft von
einem Hauptprogramm aufrufen zu können, wobei jedesmal beliebige Parameter
verwendet werden können um unterschiedliche Gleichungen zu lösen.
float quadgl()
{
.... Anweisungen ....
}
Vor Aufruf im Hauptprogramm muß zunächst die Versorgung der Variablen
a, b, c mit den gewünschten Werten erfolgen.
a = 2; b = 4; c = -20;
quadgl();
...
a = -2; b = 5; c = 31.5;
quadgl();
...
Mit den Werten a, b, und c als Parametern wird das Funktion wesentlich flexibler;
zunächst die Definition:
float quadgl (float a, float b, float c)
{
.... Anweisungen ....
}
Beim Aufruf im Hauptprogramm können nun die Parameter direkt übergeben werden:
quadgl (2, 4, -20);
...
quadgl (-2, 5, 31.5);
...
Die Parameterversorgung ist nicht auf die Angaben direkter Werte beschränkt.
Selbstverständlich lassen sich auch beliebige Variablen oder Konstante in der
Parameterliste aufführen, z. B.:
quadgl (x, y, z);
Beispiel: Berechnung eines Kreisumfangs
/* ... kreis.c ... */
#include <stdio.h>
#include <stdlib.h>
#define PI 3.1416
double circle(float rad); /* Prototyp der Funktion */
int main(void) { /* Hauptprogramm ruft Funktion auf */
double perimeter;
float radius = 5;
perimeter = circle(radius);
return 0;
}
double circle(float rad) { /* Funktionsdefinition */
double result;
result = 2.0 * rad * PI;
return result;
}
Beispiel: Steuerberechnung
Im EStG, Par. 32, ist folgendes Verfahren zur Berechnung der Einkommenssteuer
festgelegt:
Die Einkommenssteuer beträgt in deutsche Mark
- für zu versteuernde Einkommen bis 4752 DM: 0 DM;
- für zu versteuernde Einkommen von 4753 DM bis 18035 DM: 0.22x - 1045 DM;
- für zu versteuernde Einkommen von 18036 DM bis 80027 DM: (((0.34y - 21,58)y + 392)y + 2200)y + 2911 DM;
- für zu versteuernde Einkommen von 80028 DM bis 130031 DM: (70z + 4900)z + 26974 DM;
- für zu versteuernde Einkommen von 130032 DM und mehr: 0.56x-19561 DM.
Dabei ist x das abgerundete zu versteuernde Einkommen, y ein Zehntausendstel des
17982 DM übersteigenden Teils des abgerundeten zu versteuernden Einkommens, und
z ist ein Zehntausendstel des 79974 DM übersteigenden Teils des
abgerundeten zu versteuerndes Einkommens.
Das zu versteuernde Einkommen ist zunächst vor jeglicher Berechnung auf den nächsten
durch 54 ohne Rest teilbaren Betrag abzurunden, wenn es nicht bereits durch 54 ohne
Rest teilbar ist.
double Steuer(double einkommen)
{
double steuer, y;
/* Zahl muss abgerundet werden */
einkommen = floor(ein / 54) * 54;
if (einkommen < 4753)
steuer = 0;
else if (einkommen < 18036)
steuer = 0.22 * einkommen - 1045;
else if (einkommen < 80028)
{
y = (einkommen - 17982)/10000.0;
steuer = (((0.34*y - 21.58)*y + 392)*y + 2200)*y + 2911;
}
else if (einkommen < 130032)
{
y = (einkommen-79974)/10000.0;
steuer = (70*y + 4900)*y + 26974;
}
else steuer = 0.56 * einkommen - 19561;
return(steuer);
}
Feld als Übergabeparameter
Da der Name eines Feldes ein Zeiger auf das erste Element des Feldes
ist (mit anderen Worten: die Adresse des ersten Elements ist), wird bei
Feldern immer eine Adresse übergeben. Das bedeutet, daß die
Funktion immer mit dem Originalfeld arbeitet. Es findet keine
Feldgrenzenüberprüfung beim Funktionsaufruf statt.
Für die Vereinbarung der Aktualparameter hat man zwei Möglichkeiten:
- Felddeklaration:
Intern wird dann eine Typumwandlung nach Zeiger vorgenommen.
- Zeiger (siehe später).
Beispiel: Feldelemente aufaddieren; Summe auf feld[0] speichern
#include <stdio.h>
void sum(int a[5],int);
int main(void)
{
int feld[5] ={0,2,3,4,5};
int n = 3, summe;
printf("summe = %d\n",feld[0]);
sum(&feld[0],n);
printf("summe = %d\n",feld[0]);
exit(0);
}
void sum(int a[5], int n)
{
while (n-- >1)
a[0] += a[n];
return;
}
|
|
|