Die hatten Probleme damals
Früher mit Basic (Apple-Soft-Basic aus meiner Schulzeit bei Frau Knaier, ich war 15 also vor ca. 24 Jahren) aber auch heute in Assembler sieht ein Unterprogrammaufruf etwa so aus:
10 INPUT "Sag mir Deinen Namen: "; A$ 20 PRINT "Ich spring in ein Unterprogramm" 30 GOSUB 100 40 Print "Bin wieder zurueck "; A$ 50 Print 60 END 100 Print "Unterprogramm liebt "; A$ 110 A$ = A$+"chen" 120 RETURN |
Emulation mit Virtual ][
Wer Lust bekommen hat, Apple 2 Emulatoren gibt es auch für Windows.. |
GOSUB 100: Go to Subroutine 100, Gehe zum Unterprogramm zur Zeile mit der Nummer 100. Es wurde in 10er Schritten gezählt, damit man später noch leicht Zeilen einfügen konnte.
Damals gab es Probleme: Variablen waren immer Global über das ganze Programm vorhanden, man musste sich absprechen, z.B. die Variablen fingen immer mit den Initialen des Programmierers an. Die Variablen beanspruchten auch Platz wenn sie nur einmal verwendet wurden. Mein erster Rechner hatte 64KiB Hauptspeicher also (1GiB = 230; 64KiB = 216; 230-16 = 214 = 16 384) mal weniger als heute! Die Namen der Unterprogramme waren nicht sehr aussagekräftig: GOSUB 100..
Die Probleme wurden gelöst
- In Unterprogrammen gibt es lokale Variablen, die nur so lange existieren wie das Unterprogramm ausgeführt wird.
- Unterprogramme bekommen aussagekräftige Namen, die Zeilennummern wurden zunächst durch Labels (Ensprungmarken) ersetzt und dann durch Funktionen mit Parametern.
Heute würde das Programm in C so aussehen, ohne Zeilennummern aber noch mit globaler Variable a:
string a; // Globale Variable a void unter(){ // Unterprogramm muss vor erstem Aufruf deklariert / definiert werden cout << "Unterprogramm liebt " << a << endl; a = a+"chen"; } void main() { // Der Anfang hat einen Namen, er heist main() cout << "Sag mir Deinen Namen: "; cin >> a; cout << "Ich spring in ein Unterprogramm \n"; unter(); cout << "Bin wieder zurueck "<< a; cout << endl; }
Frage: Warum steht da immer void? Antwort: void heist Lücke, es wird kein Rückgabetyp angegeben.
Lokale Variablen
Die geschweiften Klammern {} halten das Unterprogramm nicht nur zusammen sondern schirmen seinen Inhalt nach aussen ab:
void unter(){ string lokal ="Der "; cout << lokal << a; } Lokale Variablen existieren nur innerhalb des Unterprogramms, ihr Speicherplatz wird nach Verlassen des Unterprogramms wieder frei gegeben. Auf die Variable lokal kann von aussen nicht zugegriffen (gelesen und geschrieben) werden. |
Datenaustausch mit Unterprogrammen
Um Daten in das Unterprogramm zu bekommen wieder globale Variablen verwenden? Wie wäre es denn mit einer "Durchreiche":
void unter(string a){ // a ist Parametervariable von unter cout << "Unterprogramm liebt " << a << endl; a = a+"chen"; } void main() { string a; // dieses a ist lokale Variable in main cout << "Sag mir Deinen Namen: "; cin >> a; cout << "Ich spring in ein Unterprogramm \n"; unter(a); cout << "Bin wieder zurueck "<< a; cout << endl; } |
|
Schreibt man die Deklarration einer lokalen Variablen in die Klammer des Unterprogramms, kann beim Aufruf des Unterprogramms der Variable ein Wert übergeben werden. Wie man an der Ausgabe erkennen kann -das "chen" fehlt, handelt es sich nicht um die selben a-Variablen, es wurde der Wert des lokalen main-a beim Aufruf in das Parameter-unter-a kopiert, dieser Aufruftyp wird Call by Value (Aufruf mit dem Wert) genannt. |
Einen Wert aus dem Unterprogramm zurück bekommen mit return
string unter(string a){ // a ist Parametervariable von unter cout << "Unterprogramm liebt " << a << endl; a = a+"chen"; return a; // gib den Wert des lokalen a zurück } void main() { string a; // dieses a ist lokale Variable in main cout << "Sag mir Deinen Namen: "; cin >> a; cout << "Ich spring in ein Unterprogramm \n"; a = unter(a); // nimm den Wert von unter(a) und weise ihn a zu cout << "Bin wieder zurueck "<< a; cout << endl; } |
Sobald in einem Unterprogramm die Anweisung return Wert ausgeführt wird endet das Unterprogramm mit der Rückgabe des Wertes.
Call by Reference
void unter(string& a){ // a ist Referenzparameter durch & cout << "Unterprogramm liebt " << a << endl; a = a+"chen"; } void main() { string a; // dieses a ist lokale Variable in main cout << "Sag mir Deinen Namen: "; cin >> a; cout << "Ich spring in ein Unterprogramm \n"; unter(a); // wende unter auf a an, a wird an unter übergeben cout << "Bin wieder zurueck "<< a; cout << endl; } |
In main() gibt es die lokale Variable a. Beim Aufruf von unter(a) wird nun nicht der Wert von a übergeben, sondern eine Referenz auf den Speicherplatz von a . Ein Zugriff in unter auf das unter-a ist wie wenn man direkt in main auf das main-a zugreift. |