Revision history for ProzProg7ProzedurenFunktionen
Additions:
----
CategoryProzeduraleProgrammierung
CategoryProzeduraleProgrammierung
Deletions:
CategoryProzeduraleProgrammierung
Additions:
CategoryProzeduraleProgrammierung
Deletions:
Additions:
CategoryDelete
Deletions:
Additions:
=====
=====7.3. Parameter =====
=====7.3. Parameter =====
Deletions:
Additions:
Beispiel: float f(){ } ""//potentielle Fehlerquelle! ""
Deletions:
Additions:
return n+ sum(n-1);
Deletions:
Additions:
{{image url="pp52.gif" width="500"}}
""⇒"" Demo 6. ""MaxMin ""
**Beispiel 2**
Die Prozedur swap vertauscht die Werte der beiden als Argumente übergebenen Variablen:
void swap (int & a, int & b )
{ int tmp= a;
a=b;
b=tmp;
int main()
{ int a=1, b=2;
cout<<a<<" "<<b<<endl; //1 2
swap(a, b);
cout<<a<<" "<<b<<endl; //2 1
} %%
Jeder Parameter wird hier zuerst als ein IN-Parameter und danach als ein OUT- Parameter verwendet.
=====7.4. Funktionsergebnis =====
===Rückgabe per Wert===
Bei der Rückgabe per Wert (return value) wird eine temporäre Kopie des Rückgabewertes an den Aufrufer zurückgegeben.
**Synonym**: Funktionswert, Rückwert, Resultatwert.
Dabei werden Ergebnisse über eine return- Anweisung zurückgeben.
int main()
{ int a=f(); //Aufruf
int f( )
{ int b=5;
return b;
""⇒"" Demo 7.
===return-Anweisung ===
Die return-Ausführung besteht aus einigen Schritten:
1. Der return-Ausdruck wird ausgewertet.
2. Der return-Ausdruck wird in den Datentyp des Funktionsergebnisses konvertiert. Dafür müssen sie typkompatibel sein.
3. Das Ergebnis wird an den Aufrufer automatisch zurückgeliefert (zurückgegeben).
4. Es folgt eine Rückkehr (Rücksprung, Rückgang) zum Aufrufer.
===Rückgabe per Referenz ===
Bei der Rückgabe per Referenz wird die Adresse vom Ergebnis zurückgegeben. Der Aufruf wird durch Alias vom Ergebnis ersetzt. Im Aufrufer wird nicht mit einer Kopie, sondern direkt mit dem Original gearbeitet.
Als return-Ausdruck sind erlaubt:
a) globale Variablen,
a) b)static-Variablen,
c) dynamische Variablen,
d) Referenzparameter,
e) keine lokalen Variablen.
int main()
{ f()=3; //Aufruf
int b=5;
int & f( )
{ return b;
""⇒"" Demo 8.
===Besonderheiten ===
1. Eine Funktion, die als Funktionsergebnis nicht den Datentyp void hat, sollte mit return immer ein Ergebnis zurückgeben. Sonst ist das Funktionsergebnis undefiniert.
Beispiel: float f(){ } //potentielle Fehlerquelle!
2. Falls kein Rückgabetyp angegeben wird, hat das Funktionsergebnis in C den Datentyp int.
3. Wenn der Datentyp des Funktionsergebnisses void ist, kann die return-Anweisung auch weggelassen werden.
4. Achtung: Begriffsverwirrung bei Funktionsergebnis vs. Ergebnisparameter, Funktionswert.
=====7.5. Details =====
===Feld als Parameter ===
Ein Feldname kann als Argument übergeben werden. Weil ein Feldname eine Adresse des ersten Elementes ist, wird eine Adresse übergeben.
Das bedeutet, daß die Funktion immer mit dem Originalfeld arbeitet. Es handelt sich also um einen impliziten call-by-reference.
**Beispiel**. Zyklisches Schieben:
int main()
{ int feld[4] =
{11, 22, 33, 44};
schieben(feld);
void schieben(int a[4])
{ int tmp=a[3];
for(int i=3; i>0; i--)
a[i]=a[i-1];
a[0]=tmp;
Ergebnis: 44 11 22 33
Ein Feldname enthält keine Information über die Feldlänge Die folgende Schreibweisen sind äquivalent:
void schieben(int a[4]);
void schieben(int a[ ]);
Es findet keine automatische Feldgrenzenüberprüfung statt. Die konkrete Feldlänge kann als zusätzliches Argument
übergegeben werden.
**Beispiel**. Funktion schieben für beliebige Feldlänge:
int main()
{ int feld[4] =
{11, 22, 33, 44};
schieben(feld, 4);
return 0;
void schieben(int a[ ], int n)
{ int tmp=a[n-1];
for(int i=n-1; i>0; i--)
a[i]=a[i-1];
a[0]=tmp;
Mehrdimensionale Felder werden als Feld von Feldern eingebaut.
Bei der Parameterübergabe wird ein zweidimensionales Feld als eindimensionales Feld mit dem komplexen Elementtyp übergeben.
Beispielweise wird im Feld int a[2][3] jedes Element vom Typ int[3] interpretiert. Die gesamte Feldlänge wird nicht übergeben.
In formalem Parameter kann die Elementanzahl linker Dimension weggelassen werden.
Die folgende Schreibweisen sind äquivalent:
void f(int a[2][3]); void f(int a[ ][3]);
""⇒"" Demo 9.
===Seiteneffekte ===
Werden innerhalb einer Funktion globale Variablen verändert, die nicht als aktuelle Parameter an diese Funktion übergeben werden, so wird dies als Seiteneffekt (Nebenwirkung) bezeichnet [Duden Informatik].
Im Allgemeinen sind Seiteneffekte zu vermeiden, weil der Anwender einer Funktion meist keine Kenntnis über Seiteneffekte hat. So sind sie oft eine Quelle versteckter und seltsamer Fehler.
Beispiele für Funktionen ohne und mit Seiteneffekt:
int dreifach(int x)
{
return 3*x;
}
int x= ...;
void dreifach (void)
{ x= 3*x;
}
===static-Variable===
Der Funktionskörper ist ein Block. Beim Betreten eines Blocks wird für lokalen Variablen und Wertparameter der Funktion Speicherplatz beschafft.
Bei Verlassen des Blocks wird der Speicherplatz freigegeben. Man sagt: Die Funktion besitzt kein Gedächtnis.
Die Ausnahme bilden static-Variablen, die genau wie globale Variablen einen festen Speicherplatz erhalten. static- Variablen verlieren nicht ihren Wert zwischen Aufrufen und wirken wie ein Gedächtnis für eine Funktion.
Sie werden nur ein einziges Mal beim ersten Aufruf der Funktion automatisch mit 0 initialisiert. static- Variablen sind globalen Variablen vorzuziehen, weil unabsichtliche Änderungen vermieden werden.
""⇒"" Demo 10.
===Rekursiver Aufruf ===
""C/C++"" erlaubt einen rekursiven Aufruf von Funktionen.
Rekursion liegt vor, wenn sich eine Funktion während ihrer Ausführung selbst aufruft.
Der Grundgedanke besteht dabei darin, durch den rekursiven Aufruf das gegebene Problem zu verkleinern. Durch rekursive Algorithmen sind oft überraschend kurze und elegante Lösungen möglich. Ein iterativer Algorithmus enthält eine Wiederholung, in der Zwischenergebnisse erzeugt werden.
Theoretisch sind Iteration und Rekursion äquivalent.
Beispiel. Summe als Iteration und Rekursion:
int sum(int n)
{ int s=0, i=0;
while(i<=n)
{ s+=i; i++;
}
return s;
}
int sum(int n)
{ if(n >0)
return n+ ""<span style="color:blue;">sum(n-1)</span>"";
return 0;
Um eine Rekursion zu erreichen, müssen lokale Variablen und Parameter bei jedem Aufruf der Funktion unter einer neuer Speicheradresse gespeichert werden. Dazu wird in der Regel ein Stack verwendet.
""⇒""Demo 11.
""⇒"" Demo 6. ""MaxMin ""
**Beispiel 2**
Die Prozedur swap vertauscht die Werte der beiden als Argumente übergebenen Variablen:
void swap (int & a, int & b )
{ int tmp= a;
a=b;
b=tmp;
int main()
{ int a=1, b=2;
cout<<a<<" "<<b<<endl; //1 2
swap(a, b);
cout<<a<<" "<<b<<endl; //2 1
} %%
Jeder Parameter wird hier zuerst als ein IN-Parameter und danach als ein OUT- Parameter verwendet.
=====7.4. Funktionsergebnis =====
===Rückgabe per Wert===
Bei der Rückgabe per Wert (return value) wird eine temporäre Kopie des Rückgabewertes an den Aufrufer zurückgegeben.
**Synonym**: Funktionswert, Rückwert, Resultatwert.
Dabei werden Ergebnisse über eine return- Anweisung zurückgeben.
int main()
{ int a=f(); //Aufruf
int f( )
{ int b=5;
return b;
""⇒"" Demo 7.
===return-Anweisung ===
Die return-Ausführung besteht aus einigen Schritten:
1. Der return-Ausdruck wird ausgewertet.
2. Der return-Ausdruck wird in den Datentyp des Funktionsergebnisses konvertiert. Dafür müssen sie typkompatibel sein.
3. Das Ergebnis wird an den Aufrufer automatisch zurückgeliefert (zurückgegeben).
4. Es folgt eine Rückkehr (Rücksprung, Rückgang) zum Aufrufer.
===Rückgabe per Referenz ===
Bei der Rückgabe per Referenz wird die Adresse vom Ergebnis zurückgegeben. Der Aufruf wird durch Alias vom Ergebnis ersetzt. Im Aufrufer wird nicht mit einer Kopie, sondern direkt mit dem Original gearbeitet.
Als return-Ausdruck sind erlaubt:
a) globale Variablen,
a) b)static-Variablen,
c) dynamische Variablen,
d) Referenzparameter,
e) keine lokalen Variablen.
int main()
{ f()=3; //Aufruf
int b=5;
int & f( )
{ return b;
""⇒"" Demo 8.
===Besonderheiten ===
1. Eine Funktion, die als Funktionsergebnis nicht den Datentyp void hat, sollte mit return immer ein Ergebnis zurückgeben. Sonst ist das Funktionsergebnis undefiniert.
Beispiel: float f(){ } //potentielle Fehlerquelle!
2. Falls kein Rückgabetyp angegeben wird, hat das Funktionsergebnis in C den Datentyp int.
3. Wenn der Datentyp des Funktionsergebnisses void ist, kann die return-Anweisung auch weggelassen werden.
4. Achtung: Begriffsverwirrung bei Funktionsergebnis vs. Ergebnisparameter, Funktionswert.
=====7.5. Details =====
===Feld als Parameter ===
Ein Feldname kann als Argument übergeben werden. Weil ein Feldname eine Adresse des ersten Elementes ist, wird eine Adresse übergeben.
Das bedeutet, daß die Funktion immer mit dem Originalfeld arbeitet. Es handelt sich also um einen impliziten call-by-reference.
**Beispiel**. Zyklisches Schieben:
int main()
{ int feld[4] =
{11, 22, 33, 44};
schieben(feld);
void schieben(int a[4])
{ int tmp=a[3];
for(int i=3; i>0; i--)
a[i]=a[i-1];
a[0]=tmp;
Ergebnis: 44 11 22 33
Ein Feldname enthält keine Information über die Feldlänge Die folgende Schreibweisen sind äquivalent:
void schieben(int a[4]);
void schieben(int a[ ]);
Es findet keine automatische Feldgrenzenüberprüfung statt. Die konkrete Feldlänge kann als zusätzliches Argument
übergegeben werden.
**Beispiel**. Funktion schieben für beliebige Feldlänge:
int main()
{ int feld[4] =
{11, 22, 33, 44};
schieben(feld, 4);
return 0;
void schieben(int a[ ], int n)
{ int tmp=a[n-1];
for(int i=n-1; i>0; i--)
a[i]=a[i-1];
a[0]=tmp;
Mehrdimensionale Felder werden als Feld von Feldern eingebaut.
Bei der Parameterübergabe wird ein zweidimensionales Feld als eindimensionales Feld mit dem komplexen Elementtyp übergeben.
Beispielweise wird im Feld int a[2][3] jedes Element vom Typ int[3] interpretiert. Die gesamte Feldlänge wird nicht übergeben.
In formalem Parameter kann die Elementanzahl linker Dimension weggelassen werden.
Die folgende Schreibweisen sind äquivalent:
void f(int a[2][3]); void f(int a[ ][3]);
""⇒"" Demo 9.
===Seiteneffekte ===
Werden innerhalb einer Funktion globale Variablen verändert, die nicht als aktuelle Parameter an diese Funktion übergeben werden, so wird dies als Seiteneffekt (Nebenwirkung) bezeichnet [Duden Informatik].
Im Allgemeinen sind Seiteneffekte zu vermeiden, weil der Anwender einer Funktion meist keine Kenntnis über Seiteneffekte hat. So sind sie oft eine Quelle versteckter und seltsamer Fehler.
Beispiele für Funktionen ohne und mit Seiteneffekt:
int dreifach(int x)
{
return 3*x;
}
int x= ...;
void dreifach (void)
{ x= 3*x;
}
===static-Variable===
Der Funktionskörper ist ein Block. Beim Betreten eines Blocks wird für lokalen Variablen und Wertparameter der Funktion Speicherplatz beschafft.
Bei Verlassen des Blocks wird der Speicherplatz freigegeben. Man sagt: Die Funktion besitzt kein Gedächtnis.
Die Ausnahme bilden static-Variablen, die genau wie globale Variablen einen festen Speicherplatz erhalten. static- Variablen verlieren nicht ihren Wert zwischen Aufrufen und wirken wie ein Gedächtnis für eine Funktion.
Sie werden nur ein einziges Mal beim ersten Aufruf der Funktion automatisch mit 0 initialisiert. static- Variablen sind globalen Variablen vorzuziehen, weil unabsichtliche Änderungen vermieden werden.
""⇒"" Demo 10.
===Rekursiver Aufruf ===
""C/C++"" erlaubt einen rekursiven Aufruf von Funktionen.
Rekursion liegt vor, wenn sich eine Funktion während ihrer Ausführung selbst aufruft.
Der Grundgedanke besteht dabei darin, durch den rekursiven Aufruf das gegebene Problem zu verkleinern. Durch rekursive Algorithmen sind oft überraschend kurze und elegante Lösungen möglich. Ein iterativer Algorithmus enthält eine Wiederholung, in der Zwischenergebnisse erzeugt werden.
Theoretisch sind Iteration und Rekursion äquivalent.
Beispiel. Summe als Iteration und Rekursion:
int sum(int n)
{ int s=0, i=0;
while(i<=n)
{ s+=i; i++;
}
return s;
}
int sum(int n)
{ if(n >0)
return n+ ""<span style="color:blue;">sum(n-1)</span>"";
return 0;
Um eine Rekursion zu erreichen, müssen lokale Variablen und Parameter bei jedem Aufruf der Funktion unter einer neuer Speicheradresse gespeichert werden. Dazu wird in der Regel ein Stack verwendet.
""⇒""Demo 11.
Deletions:
""⇒"" Demo 6. MaxMin
Additions:
1) call-by-reference ist nur in ""C++"" möglich.
Deletions:
Additions:
===call-by-reference ===
Bei der Adressübergabe (call by reference) werden der Funktion die Speicheradressen der aktuellen Parameter des Aufrufers übergeben.
Der formale Parameter enthält Symbol **&** und wird als Referenzparameter bezeichnet. Der formale Parameter ist dann ein anderer Name (Alias) für das Argument.
Die Funktion arbeitet nicht mit der Kopie des Argumentes sondern direkt mit dem Original.
Der Datenfluss kann in beide Richtungen gehen. Deswegen wird ein solcher Parameter als Eingangs-Ausgangsparameter (IN-OUT-Parameter) bezeichnet.
**Anmerkungen**:
1) call-by-reference ist nur in C++ möglich.
2) Das Symbol **&** (Ampersand) in der Parameter-Definition ist kein Adress-Operator.
**Vorteile**:
1) Es besteht kein Zeitaufwand fürs Kopieren des Argumentes.
2) Über Referenzparameter können mehrere Ergebnisse zurückgeliefert werden. Ein einziges Ergebnis kann als Funktionsergebnis gestaltet werden.
**Nachteil**: Es besteht die Gefahr unbeabsichtigter Veränderungen des Argumentes.
**Achtung: **
Begriffsverwirrung bei Eingangs- Ausgangsparameter vs. Eingabe- Ausgabeparameter!
**Analogie**: Schiebemulde
**Beispiel: **
{ int a=5; f(a);
cout<<a;
return 0;
}
void f( int & a1)
{ a1=7;
""⇒"" Demo 5
**Beispiel 1**
Entwerfen Sie ein Unterprogramm, welches zwei Zahlen vergleicht und die maximalen und minimalen Werte zurückliefert.
**Ergebnisse und Operanden: **
{{image url="pp21.gif" width="500"}}
**Entwurf der Schnittstelle: **
a und b sind IN-Parameter, max und min sind IN-OUT-Parameter:
void minMax(int a, int b, int & max, int & min);
""⇒"" Demo 6. MaxMin
Bei der Adressübergabe (call by reference) werden der Funktion die Speicheradressen der aktuellen Parameter des Aufrufers übergeben.
Der formale Parameter enthält Symbol **&** und wird als Referenzparameter bezeichnet. Der formale Parameter ist dann ein anderer Name (Alias) für das Argument.
Die Funktion arbeitet nicht mit der Kopie des Argumentes sondern direkt mit dem Original.
Der Datenfluss kann in beide Richtungen gehen. Deswegen wird ein solcher Parameter als Eingangs-Ausgangsparameter (IN-OUT-Parameter) bezeichnet.
**Anmerkungen**:
1) call-by-reference ist nur in C++ möglich.
2) Das Symbol **&** (Ampersand) in der Parameter-Definition ist kein Adress-Operator.
**Vorteile**:
1) Es besteht kein Zeitaufwand fürs Kopieren des Argumentes.
2) Über Referenzparameter können mehrere Ergebnisse zurückgeliefert werden. Ein einziges Ergebnis kann als Funktionsergebnis gestaltet werden.
**Nachteil**: Es besteht die Gefahr unbeabsichtigter Veränderungen des Argumentes.
**Achtung: **
Begriffsverwirrung bei Eingangs- Ausgangsparameter vs. Eingabe- Ausgabeparameter!
**Analogie**: Schiebemulde
**Beispiel: **
{ int a=5; f(a);
cout<<a;
return 0;
}
void f( int & a1)
{ a1=7;
""⇒"" Demo 5
**Beispiel 1**
Entwerfen Sie ein Unterprogramm, welches zwei Zahlen vergleicht und die maximalen und minimalen Werte zurückliefert.
**Ergebnisse und Operanden: **
{{image url="pp21.gif" width="500"}}
**Entwurf der Schnittstelle: **
a und b sind IN-Parameter, max und min sind IN-OUT-Parameter:
void minMax(int a, int b, int & max, int & min);
""⇒"" Demo 6. MaxMin
Additions:
=====""<h2>7.3. Parameter</h2>"" =====
Deletions:
Additions:
Die Begriffe Parameter und Argument sind im ""C++-Standard"" folgendermaßen definiert:
Deletions:
Additions:
=====7.3. Parameter =====
===Datenaustausch über Parameter===
__Parameter __sind Daten, die beim Aufruf vom Aufrufer zu aufgerufener Funktion automatisch übergeben werden.
Die wichtige Besonderheit des Datenaustausches über Parameter ist der automatische Datentransfer vom Aufrufer zur aufgerufenen Funktion.
Die Begriffe Parameter und Argument sind im C++-Standard folgendermaßen definiert:
1) __Parameter __oder __formaler Parameter __wird bei einer Funktionsdeklaration (bzw. Definition) verwendet und
2) __Argument __oder __aktueller Parameter __bei einem Funktionsaufruf.
Ein formaler Parameter wird als Platzhalter für den aktuellen Parameter bezeichnet.
===Parameterliste===
Alle Parameter einer Funktion sind in einer Parameterliste zusammengestellt.
Eine Parameterliste einer parameterlosen Funktion ist entweder leer oder besteht nur aus dem Datentyp void. Die Liste aktueller Parameter muß mit der Liste der formalen Parameter nach Anzahl, Reihenfolge und Typ der Parameter übereinstimmen.
Beim Aufruf einer Funktion muss normalerweise für jeden formalen Parameter ein Argument eingesetzt werden.
Analogie: Die Parameterlisten mit den formalen Parametern und die Parameterliste mit den aktuellen Parameter müssen zusammenpassen wie Stecker und Kupplung einer elektrischen Verbindung.
===Übereinstimmung. Beispiel ===
{{image url="pp51.gif" width="500"}}
===Aufruf===
Die Verwendung einer Funktion wird allgemein auch Funktions-Aufruf genannt. Ein Aufruf ist eine komplexe Anweisung und besteht aus einigen Schritten:
1. Alle Argumente werden ausgewertet, z.B. die Argumente können Ausdrücke sein.
2. Zusammengehörige Parameter werden konvertiert, wenn sie verschiedene Typen besitzen. Dafür müssen sie Typkompatibel sein.
3. Die aktuellen Parameter werden an die Funktion übergeben.
4. Es folgt eine Vorbereitung der Rückkehr zum Aufrufer.
5. Es folgt ein Sprung (Übergang, Kontrollübergabe) zur aufgerufenen Funktion.
===call-by-value===
Bei der Wertübergabe (call by value) wird an die Funktion Kopien der aktuellen Parameter des Aufrufers übergeben.
Der Datenfluss geht nur in die Funktion hinein. Deswegen wird ein solcher Parameter als Eingangsparameter (IN-Parameter) bezeichnet.
**Vorteil**: Die Funktion kann den aktuellen Parameter des Aufrufers nicht verändern.
**Nachteil**: Das Kopieren des aktuellen Parameters kann mit einem größeren Zeitaufwand verbunden sein, wenn dieser Parameter vom „großen“ Datentyp ist.
**Beispiel**:
int main()
{ int a=5; f(a);
return 0;
}
void f(int a1)
{ cout<<a1;
}
""⇒"" Demo 4.
===Datenaustausch über Parameter===
__Parameter __sind Daten, die beim Aufruf vom Aufrufer zu aufgerufener Funktion automatisch übergeben werden.
Die wichtige Besonderheit des Datenaustausches über Parameter ist der automatische Datentransfer vom Aufrufer zur aufgerufenen Funktion.
Die Begriffe Parameter und Argument sind im C++-Standard folgendermaßen definiert:
1) __Parameter __oder __formaler Parameter __wird bei einer Funktionsdeklaration (bzw. Definition) verwendet und
2) __Argument __oder __aktueller Parameter __bei einem Funktionsaufruf.
Ein formaler Parameter wird als Platzhalter für den aktuellen Parameter bezeichnet.
===Parameterliste===
Alle Parameter einer Funktion sind in einer Parameterliste zusammengestellt.
Eine Parameterliste einer parameterlosen Funktion ist entweder leer oder besteht nur aus dem Datentyp void. Die Liste aktueller Parameter muß mit der Liste der formalen Parameter nach Anzahl, Reihenfolge und Typ der Parameter übereinstimmen.
Beim Aufruf einer Funktion muss normalerweise für jeden formalen Parameter ein Argument eingesetzt werden.
Analogie: Die Parameterlisten mit den formalen Parametern und die Parameterliste mit den aktuellen Parameter müssen zusammenpassen wie Stecker und Kupplung einer elektrischen Verbindung.
===Übereinstimmung. Beispiel ===
{{image url="pp51.gif" width="500"}}
===Aufruf===
Die Verwendung einer Funktion wird allgemein auch Funktions-Aufruf genannt. Ein Aufruf ist eine komplexe Anweisung und besteht aus einigen Schritten:
1. Alle Argumente werden ausgewertet, z.B. die Argumente können Ausdrücke sein.
2. Zusammengehörige Parameter werden konvertiert, wenn sie verschiedene Typen besitzen. Dafür müssen sie Typkompatibel sein.
3. Die aktuellen Parameter werden an die Funktion übergeben.
4. Es folgt eine Vorbereitung der Rückkehr zum Aufrufer.
5. Es folgt ein Sprung (Übergang, Kontrollübergabe) zur aufgerufenen Funktion.
===call-by-value===
Bei der Wertübergabe (call by value) wird an die Funktion Kopien der aktuellen Parameter des Aufrufers übergeben.
Der Datenfluss geht nur in die Funktion hinein. Deswegen wird ein solcher Parameter als Eingangsparameter (IN-Parameter) bezeichnet.
**Vorteil**: Die Funktion kann den aktuellen Parameter des Aufrufers nicht verändern.
**Nachteil**: Das Kopieren des aktuellen Parameters kann mit einem größeren Zeitaufwand verbunden sein, wenn dieser Parameter vom „großen“ Datentyp ist.
**Beispiel**:
int main()
{ int a=5; f(a);
return 0;
}
void f(int a1)
{ cout<<a1;
}
""⇒"" Demo 4.
Additions:
<b style="float:left;">Schnittstelle</b>
===Gültigkeitsbereiche===
1. Mit Blöcken werden Gültigkeitsbereiche geschaffen.
2. Funktionen sind benannte Blöcke und mit ihnen werden auch Gültigkeitsbereiche geschaffen.
3. Der umfassende Gültigkeitsbereich wird als globaler Gültigkeitsbereich bezeichnet.
4. Funktionen dürfen nur außerhalb jedes Blocks, d.h. global definiert werden.
5. Funktionen können nicht in andere Funktionen geschachtelt werden. Sie können aber unbenannte Blöcke enthalten.
6. Unbenannte Blöcke dürfen nur in einer Funktion enthalten sein. Sie können aber ineinander geschachtelt werden.
===Datenaustausch über globale Variablen ===
1. Variablen werden als __lokal/global __bezeichnet, wenn sie innerhalb/außerhalb eines Blocks definiert sind.
2. In geschachtelten Blöcken haben __innere/äußere __Blöcke die inneren/äußeren lokalen Variablen.
3. Innere Blöcke haben den Zugriff auf die Variablen der äußeren Blöcke. Mehrere innere Blöcke können die äußeren Variablen gemeinsam für den Datenaustausch verwenden.
4. Die globalen Variablen sind äußere Variablen für die globalen Funktionen und können als gemeinsame Variablen für den Datenaustausch verwendet werden.
%%(cpp)
int a;
void f(){ cout<<a; }
int main() { a=5; f(); return 0;}
%%
""⇒"" Demo 2. globale
5. Namen, die lokal vereinbart wurden, sind außerhalb der Funktion unbekannt. Somit können verschiedene Funktionen Variablen gleichen Namens verwenden, ohne dass ein Konflikt entsteht.
6. Globale Variablen werden durch lokale Variablen gleichen Namens überdeckt. Bei Verlassen des inneren Blocks ist die äußere Variable wieder sichtbar.
Eine globale Variable besitzt zwar eine Lebensdauer, die vom Programmbegin bis zum Programmende reicht, der Gültigkeitsbereich kann hingegen "Löcher" haben.
7. Nachteil von globalen Variablen: Jede Funktion hat eine Zugriffsmöglichkeit auf mehrere (alle) globale Variablen. Es besteht die Gefahr unbeabsichtigter Veränderungen globaler Werte.
""⇒"" Demo 3. Überdeckung
===Gültigkeitsbereiche===
1. Mit Blöcken werden Gültigkeitsbereiche geschaffen.
2. Funktionen sind benannte Blöcke und mit ihnen werden auch Gültigkeitsbereiche geschaffen.
3. Der umfassende Gültigkeitsbereich wird als globaler Gültigkeitsbereich bezeichnet.
4. Funktionen dürfen nur außerhalb jedes Blocks, d.h. global definiert werden.
5. Funktionen können nicht in andere Funktionen geschachtelt werden. Sie können aber unbenannte Blöcke enthalten.
6. Unbenannte Blöcke dürfen nur in einer Funktion enthalten sein. Sie können aber ineinander geschachtelt werden.
===Datenaustausch über globale Variablen ===
1. Variablen werden als __lokal/global __bezeichnet, wenn sie innerhalb/außerhalb eines Blocks definiert sind.
2. In geschachtelten Blöcken haben __innere/äußere __Blöcke die inneren/äußeren lokalen Variablen.
3. Innere Blöcke haben den Zugriff auf die Variablen der äußeren Blöcke. Mehrere innere Blöcke können die äußeren Variablen gemeinsam für den Datenaustausch verwenden.
4. Die globalen Variablen sind äußere Variablen für die globalen Funktionen und können als gemeinsame Variablen für den Datenaustausch verwendet werden.
%%(cpp)
int a;
void f(){ cout<<a; }
int main() { a=5; f(); return 0;}
%%
""⇒"" Demo 2. globale
5. Namen, die lokal vereinbart wurden, sind außerhalb der Funktion unbekannt. Somit können verschiedene Funktionen Variablen gleichen Namens verwenden, ohne dass ein Konflikt entsteht.
6. Globale Variablen werden durch lokale Variablen gleichen Namens überdeckt. Bei Verlassen des inneren Blocks ist die äußere Variable wieder sichtbar.
Eine globale Variable besitzt zwar eine Lebensdauer, die vom Programmbegin bis zum Programmende reicht, der Gültigkeitsbereich kann hingegen "Löcher" haben.
7. Nachteil von globalen Variablen: Jede Funktion hat eine Zugriffsmöglichkeit auf mehrere (alle) globale Variablen. Es besteht die Gefahr unbeabsichtigter Veränderungen globaler Werte.
""⇒"" Demo 3. Überdeckung
Deletions:
Additions:
""<table class="data" width="80%" style="border:0">
<tr>
<td>
<b style="float:right;">Datenflussrichtung</b><br/>
<b style="float:right;">Schnittstelle</b>
</td>
<td>
<b>In die Funktion
hinein </b>
</td>
<td>
<b> Aus der
Funktion
heraus </b>
</td>
<td>
<b> In beide
Richtungen </b>
</td>
</tr>
<tr>
<td>
<b>Globale
Variablen</b>
</td>
<td>
kein
</td>
<td>
kein
</td>
<td>
über globale
Variablen
</td>
</tr>
<tr>
<td rowspan="2">
<b>Parameter</b>
</td>
<td>
call-by-value
</td>
<td rowspan="2">
kein
</td>
<td>
call-by-
reference
</td>
</tr>
<tr>
<td>
call-by-reference
auf const
</td>
<td>
per Zeiger
</td>
</tr>
<tr>
<td rowspan="3">
Funktionsergebnis
</td>
<td rowspan="3">
kein
</td>
<td>
per Wert
</td>
<td rowspan="3">
kein
</td>
</tr>
<tr>
<td>
per Referenz
</td>
</tr>
<tr>
<td>
per Zeiger
</td>
</tr>
</table>""
<tr>
<td>
<b style="float:right;">Datenflussrichtung</b><br/>
<b style="float:right;">Schnittstelle</b>
</td>
<td>
<b>In die Funktion
hinein </b>
</td>
<td>
<b> Aus der
Funktion
heraus </b>
</td>
<td>
<b> In beide
Richtungen </b>
</td>
</tr>
<tr>
<td>
<b>Globale
Variablen</b>
</td>
<td>
kein
</td>
<td>
kein
</td>
<td>
über globale
Variablen
</td>
</tr>
<tr>
<td rowspan="2">
<b>Parameter</b>
</td>
<td>
call-by-value
</td>
<td rowspan="2">
kein
</td>
<td>
call-by-
reference
</td>
</tr>
<tr>
<td>
call-by-reference
auf const
</td>
<td>
per Zeiger
</td>
</tr>
<tr>
<td rowspan="3">
Funktionsergebnis
</td>
<td rowspan="3">
kein
</td>
<td>
per Wert
</td>
<td rowspan="3">
kein
</td>
</tr>
<tr>
<td>
per Referenz
</td>
</tr>
<tr>
<td>
per Zeiger
</td>
</tr>
</table>""
Additions:
2. Der Datenfluss geht nur in eine Funktion ""<span style="color:blue;">hinein</span>"". Dabei kann eine Funktion ein Operand übernehmen.
3. Der Datenfluss geht nur aus einer Funktion ""<span style="color:blue;">heraus</span>"". Dabei kann eine Funktion ein Ergebnis zurückliefern.
3. Der Datenfluss geht nur aus einer Funktion ""<span style="color:blue;">heraus</span>"". Dabei kann eine Funktion ein Ergebnis zurückliefern.
Deletions:
3. Der Datenfluss geht nur aus einer Funktion span style="color:blue;">heraus</span>"". Dabei kann eine Funktion ein Ergebnis zurückliefern.
Additions:
{{image class="right" url="pp50.gif" width="200"}}
Deletions:
Additions:
{{image class="right" url="pp50.gif" width="350"}}
Deletions:
Additions:
{{image class="center" url="pp49.gif" width="450"}}
=====7.2. Datenaustausch zwischen Funktionen =====
===Datenaustausch===
Aufrufende und aufgerufene Funktionen müssen untereinander Daten austauschen können. Funktionen können Daten als Operanden erhalten und können Daten als Ergebnisse zurückliefern.
Es gibt verschiedene Mechanismen für den Datenaustausch (Datentransfer) zwischen Funktionen.
Austausch-Mechanismen könnte nach der Art von Schnittstellen und nach der Datenflussrichtung klassifiziert werden.
Es gibt drei Schnittstellen für den Datenaustausch zwischen Funktionen:
1) über globale Variablen,
2) über Parameter,
3) über das Funktionsergebnis.
===Datenflussrichtung===
{{image class="right" url="pp49.gif" width="350"}}
1. Der Datenfluss geht in ""<span style="color:blue;">beide</span>"" Richtungen. Dabei können Operanden und Ergebnisse ausgetauscht werden.
2. Der Datenfluss geht nur in eine Funktion span style="color:blue;">hinein</span>"". Dabei kann eine Funktion ein Operand übernehmen.
3. Der Datenfluss geht nur aus einer Funktion span style="color:blue;">heraus</span>"". Dabei kann eine Funktion ein Ergebnis zurückliefern.
Analogie: Drehkreuz
===Klassifizierung von Austausch-Mechanismen ===
In dieser Klassifikation sind 8 Austausch-Mechanismen vorgestellt.
=====7.2. Datenaustausch zwischen Funktionen =====
===Datenaustausch===
Aufrufende und aufgerufene Funktionen müssen untereinander Daten austauschen können. Funktionen können Daten als Operanden erhalten und können Daten als Ergebnisse zurückliefern.
Es gibt verschiedene Mechanismen für den Datenaustausch (Datentransfer) zwischen Funktionen.
Austausch-Mechanismen könnte nach der Art von Schnittstellen und nach der Datenflussrichtung klassifiziert werden.
Es gibt drei Schnittstellen für den Datenaustausch zwischen Funktionen:
1) über globale Variablen,
2) über Parameter,
3) über das Funktionsergebnis.
===Datenflussrichtung===
{{image class="right" url="pp49.gif" width="350"}}
1. Der Datenfluss geht in ""<span style="color:blue;">beide</span>"" Richtungen. Dabei können Operanden und Ergebnisse ausgetauscht werden.
2. Der Datenfluss geht nur in eine Funktion span style="color:blue;">hinein</span>"". Dabei kann eine Funktion ein Operand übernehmen.
3. Der Datenfluss geht nur aus einer Funktion span style="color:blue;">heraus</span>"". Dabei kann eine Funktion ein Ergebnis zurückliefern.
Analogie: Drehkreuz
===Klassifizierung von Austausch-Mechanismen ===
In dieser Klassifikation sind 8 Austausch-Mechanismen vorgestellt.
Deletions:
Additions:
(2) Ausführung des Unterprogramms.
(3) Rückkehr zur Anweisung nach dem Aufruf.
===Aufbau eines Unterprogramms===
Bei der Definition wird ein Kopf und ein Rumpf festgelegt:
{{image class="center" url="pp46.gif" width="500"}}
Der Kopf beschreibt alle Informationen, die zum Aufruf notwendig sind. Der Rumpf ist ein ""<span style="color:blue;">Block</span>"", der beim Aufruf ausgeführt wird.
Durch die Definition wird Speicherplatz belegt (für bestimmte Variablen und den Code). Unterprogrammen dürfen nur außerhalb jedes Blocks definiert werden.
===Klassifikation ===
{{image class="center" url="pp47.gif" width="500"}}
In der Sprache ""C/C++"" werden Unterprogramme als Funktionen und Prozeduren als „void Funktionen“ bezeichnet.
===Prozeduren===
Eine Prozedur ist ein Unterprogramm, welches keinen Rückgabewert zurückliefert. Der Aufruf einer Prozedur ist deswegen eine Anweisung. Eine Prozedur hat kein resulttype. ""In C/C++"" wird der resulttype der Prozedur mit dem fiktiven leeren Datentyp void spezifiziert.
**Beispiel**:
{{image class="center" url="pp48.gif" width="500"}}
""⇒"" Demo 1. Prozedur
===Funktionen===
Eine Funktion ist ein Unterprogramm, welches ein Funktionsergebnis (Rückgabe, Resultat) zurückliefert.
Der Aufruf einer Funktion ist deswegen ein Ausdruck. Der Aufruf wird durch das Funktionsergebnis ersetzt.
In ""C/C++"" wird das Funktionsergebnis mittels der Anweisung return explizit zurückgegeben. Dabei wird das Unterprogramm sofort verlassen.
**Beispiel**:
{{image class="center" url="pp49.gif" width="500"}}
(3) Rückkehr zur Anweisung nach dem Aufruf.
===Aufbau eines Unterprogramms===
Bei der Definition wird ein Kopf und ein Rumpf festgelegt:
{{image class="center" url="pp46.gif" width="500"}}
Der Kopf beschreibt alle Informationen, die zum Aufruf notwendig sind. Der Rumpf ist ein ""<span style="color:blue;">Block</span>"", der beim Aufruf ausgeführt wird.
Durch die Definition wird Speicherplatz belegt (für bestimmte Variablen und den Code). Unterprogrammen dürfen nur außerhalb jedes Blocks definiert werden.
===Klassifikation ===
{{image class="center" url="pp47.gif" width="500"}}
In der Sprache ""C/C++"" werden Unterprogramme als Funktionen und Prozeduren als „void Funktionen“ bezeichnet.
===Prozeduren===
Eine Prozedur ist ein Unterprogramm, welches keinen Rückgabewert zurückliefert. Der Aufruf einer Prozedur ist deswegen eine Anweisung. Eine Prozedur hat kein resulttype. ""In C/C++"" wird der resulttype der Prozedur mit dem fiktiven leeren Datentyp void spezifiziert.
**Beispiel**:
{{image class="center" url="pp48.gif" width="500"}}
""⇒"" Demo 1. Prozedur
===Funktionen===
Eine Funktion ist ein Unterprogramm, welches ein Funktionsergebnis (Rückgabe, Resultat) zurückliefert.
Der Aufruf einer Funktion ist deswegen ein Ausdruck. Der Aufruf wird durch das Funktionsergebnis ersetzt.
In ""C/C++"" wird das Funktionsergebnis mittels der Anweisung return explizit zurückgegeben. Dabei wird das Unterprogramm sofort verlassen.
**Beispiel**:
{{image class="center" url="pp49.gif" width="500"}}
Deletions:
(3) Rückkehr zur Anweisung nach dem Aufruf.
Additions:
===Grundidee===
Ein Unterprogramm ist ein Teil eines Programms, welches:
1) einen Namen besitzt,
2) gestartet bzw. aufgerufen werden kann.
**Synonyme**: Funktion, Prozedur, Subroutine, Routine, benannter Block.
Unterprogramme dienen einer strukturierten Programmierung. **Einige Ziele**:
a) Zerlegung eines komplexen Gesamtproblems in Teilprobleme,
b) Wiederverwendung des Codes,
c)Lesbarkeit des Codes.
Programme bestehen typischerweise aus vielen kleinen und nicht aus wenigen großen Unterprogrammen.
===Ablauf ===
{{image class="center" url="pp45.gif" width="500"}}
Der Ablauf eines Unterprogramms erfolgt in drei Schritten:
(1) Aufruf und Sprung zum Unterprogramm.
(2) Ausführung des Unterprogramms.
(3) Rückkehr zur Anweisung nach dem Aufruf.
**Achtung**: Begriffsverwirrung bei Ablauf vs. Aufruf!
Ein Unterprogramm ist ein Teil eines Programms, welches:
1) einen Namen besitzt,
2) gestartet bzw. aufgerufen werden kann.
**Synonyme**: Funktion, Prozedur, Subroutine, Routine, benannter Block.
Unterprogramme dienen einer strukturierten Programmierung. **Einige Ziele**:
a) Zerlegung eines komplexen Gesamtproblems in Teilprobleme,
b) Wiederverwendung des Codes,
c)Lesbarkeit des Codes.
Programme bestehen typischerweise aus vielen kleinen und nicht aus wenigen großen Unterprogrammen.
===Ablauf ===
{{image class="center" url="pp45.gif" width="500"}}
Der Ablauf eines Unterprogramms erfolgt in drei Schritten:
(1) Aufruf und Sprung zum Unterprogramm.
(2) Ausführung des Unterprogramms.
(3) Rückkehr zur Anweisung nach dem Aufruf.
**Achtung**: Begriffsverwirrung bei Ablauf vs. Aufruf!
Deletions:
Additions:
======Prozedurale Programmierung - Kapitel 7 - Prozeduren und Funktionen======
{{files}}
{{files}}