Subroutine
Im Computerprogrammierung, a Subroutine ist eine Sequenz von Programmanweisungen Dies führt eine bestimmte Aufgabe aus, die als Einheit verpackt ist. Diese Einheit kann dann in Programmen verwendet werden, wo immer diese bestimmte Aufgabe ausgeführt werden soll.
Unterroutinen können in Programmen definiert werden oder getrennt in Bibliotheken Das kann von vielen Programmen verwendet werden. In verschiedenen Programmiersprachen kann eine Unterprogramme genannt werden Routine, Unterprogramm, Funktion, Methode, oder Verfahren. Technisch gesehen haben diese Begriffe alle unterschiedliche Definitionen, und die Nomenklatur variiert von Sprache zu Sprache. Der generische, Dachbegriff Anrufeinheit wird manchmal verwendet.[1]
Der Name Unterprogramm schlägt vor, dass sich eine Unterroutine ähnlich wie ein Computerprogramm verhält, das als ein Schritt in einem größeren Programm oder einem anderen Subprogramm verwendet wird. Eine Unterroutine wird häufig so codiert, dass sie mehrmals und von mehreren Stellen während einer Ausführung des Programms, einschließlich anderer Unterprogramme, und anschließend zurückgezeigt werden kann.Rückkehr) zur nächsten Anweisung nach dem AnrufSobald die Aufgabe des Unterprogramms erledigt ist. Die Idee einer Unterroutine wurde ursprünglich von konzipiert von John Mauchly während seiner Arbeit an Eniac,[2] und in einem Harvard-Symposium im Januar 1947 zur "Herstellung von Problemen für EDVAC-Maschinen" aufgezeichnet.[3] Maurice Wilkes, David Wheeler, und Stanley Gill werden im Allgemeinen der formalen Erfindung dieses Konzepts zugeschrieben, das sie als a bezeichneten geschlossene Unterroutine,[4][5] im Gegensatz zu einem Offene Unterroutine oder Makro.[6] Jedoch, Turing hatte Unterroutinen in einem Papier von 1945 über Konstruktionsvorschläge für die NPL besprochen ASdas Konzept eines Rückgabedressenstacks so weit, das Konzept eines Rückgabedresses zu erfinden.[7]
Unterroutinen sind mächtig Programmierung Werkzeug,[8] und die Syntax von vielen Programmiersprachen Beinhaltet Unterstützung für das Schreiben und die Verwendung. Vernünftiger Gebrauch von Unterroutinen (zum Beispiel durch die Strukturierte Programmierung Ansatz) reduziert häufig die Kosten für die Entwicklung und Aufrechterhaltung eines großen Programms erheblich und erhöht die Qualität und Zuverlässigkeit.[9] Unterroutinen, oft gesammelt in Bibliotheken, sind ein wichtiger Mechanismus zum Teilen und Handelssoftware. Die Disziplin von Objekt orientierte Programmierung basiert auf Objekte und Methoden (Die Unterroutinen sind an diese Objekte oder Objekte angehängt Klassen).
In dem Kompilieren Methode aufgerufen Thread -CodeDas ausführbare Programm ist im Grunde eine Folge von Unterroutine -Anrufen.
Hauptkonzepte
Der Inhalt einer Unterroutine ist sein Körper, der das Programm Code ist, der ausgeführt wird, wenn das Unterprogramm aufgerufen oder aufgerufen wird.
Es kann ein Unterprogramm so geschrieben werden, dass sie erwartet, einen oder mehrere Datenwerte aus dem aufrufenden Programm zu erhalten (um seine zu ersetzen Parameter oder formale Parameter). Das aufrufende Programm enthält tatsächliche Werte für diese Parameter genannt Argumente. Unterschiedliche Programmiersprachen können unterschiedliche Konventionen verwenden, um Argumente zu übergeben:
Konvention | Beschreibung | Allgemeiner Gebrauch |
---|---|---|
Rufen Sie nach Wert an | Das Argument wird bewertet und die Kopie des Wertes an Unterroutine übergeben | Standardeinstellung in den meisten algolähnlichen Sprachen danach Algol 60wie Pascal, Delphi, Simula, Cpl, PL/M, Modula, Oberon, ADA und viele andere. C, C ++, Java (Verweise auf Objekte und Arrays werden ebenfalls mit Wert übergeben) |
Rufen Sie durch Referenz an | Verweis auf ein Argument, normalerweise wird seine Adresse übergeben | In den meisten algolähnlichen Sprachen ausgewählt werden Algol 60, wie Algol 68, Pascal, Delphi, Simula, Cpl, PL/M, Modula, Oberon, ADA und viele andere. C ++, Forran, Pl/i |
Rufen Sie nach Ergebnis an | Der Parameterwert wird bei der Rückkehr aus der Unterroutine wieder in das Argument kopiert | ADA OUT -Parameter |
Rufen Sie nach wertvoller Result an | Der Parameterwert wird beim Eintrag in die Unterroutine und erneut bei der Rückgabe kopiert | Algol, Schnell In-out-Parameter |
Rufen Sie mit dem Namen an | Ersetzen Sie wie ein Makro die Parameter durch die nicht evaluierten Argumentausdrücke und bewerten Sie das Argument im Kontext des Anrufers jedes Mal, wenn die aufgerufene Routine den Parameter verwendet. | Algol, Scala |
Anruf nach konstantem Wert | Wie aufruf nach Wert, außer dass der Parameter als Konstante behandelt wird | PL/I nicht signierbare Parameter, ADA in Parametern |
Ein Unterroutine -Anruf kann auch haben Nebenwirkungen wie Änderungen Datenstrukturen in einem Computerspeicher, Lesen oder Schreiben an a peripheres Gerät, ein ... Erstellen DateiAnhalten des Programms oder der Maschine oder sogar die Verzögerung der Ausführung des Programms für eine bestimmte Zeit. Ein Unterprogramm mit Nebenwirkungen kann jedes Mal, wenn es aufgerufen wird, unterschiedliche Ergebnisse zurückgeben, auch wenn es mit denselben Argumenten aufgerufen wird. Ein Beispiel ist a Zufallszahl Unterroutine, in vielen Sprachen erhältlich, die jedes Mal, wenn sie aufgerufen wird, eine andere Pseudo-Random-Nummer zurückgibt. Die weit verbreitete Verwendung von Unterroutinen mit Nebenwirkungen ist eine Merkmale von Imperative Programmierung Sprachen.
Ein Unterroutine kann so codiert werden, dass sie dies kann Nennen Sie sich rekursivan einem oder mehreren Orten, um seine Aufgabe auszuführen. Diese Methode ermöglicht eine direkte Implementierung von Funktionen, die durch definiert wurden, mathematische Induktion und rekursiv Algorithmen teilen und erobern.
Ein Unterprogramm, dessen Ziel ist, einen zu berechnen boolesche Wertfunktion (Das heißt, eine Ja/Nein -Frage zu beantworten) wird manchmal als Prädikat bezeichnet. Im Logikprogrammierung Sprachen oft[vage] Alle Unterprogramme werden als Prädikate bezeichnet, da sie hauptsächlich[vage] Erfolg oder Misserfolg bestimmen.
Eine Unterprogramme, die keinen Wert zurückgibt oder einen Nullwert zurückgibt, wird manchmal als Verfahren bezeichnet. Verfahren ändern normalerweise ihre Argumente und sind ein zentraler Bestandteil von Verfahrensprogrammierung.
Funktionen
A Funktion ist eine Unterroutine, die einen Wert zurückgibt.[10] Der Hauptzweck von Funktionen besteht darin, komplizierte Berechnungen in aussagekräftige Stücke aufzuteilen und sie zu benennen.[11] Die Unterroutine kann einen berechneten Wert an seinen Anrufer (ITS "zurückgeben Rückgabewert) oder verschiedene Ergebniswerte oder Ausgabeparameter bereitstellen. In der Tat ist eine häufige Verwendung von Unterroutinen implementiert Mathematische Funktionen, in dem der Zweck der Unterroutine nur darin besteht, ein oder mehrere Ergebnisse zu berechnen, deren Werte vollständig durch die an die Unterroutine übergebenen Argumente bestimmt werden. (Beispiele können das Berechnen der berechnen Logarithmus einer Zahl oder der bestimmend von a Matrix.) In einigen Sprachen ist die Syntax für eine Prozedur, die einen Wert zurückgibt, im Wesentlichen die gleiche wie die Syntax für eine Prozedur, die keinen Wert zurückgibt, mit Ausnahme des Fehlens von, z. B. Rückgabebereich. In einigen Sprachen kann sich eine Prozedur je nach Argumenten dynamisch mit oder ohne Wert zurückgeben.
Sprachunterstützung
Hochrangige Programmiersprachen Fügen Sie normalerweise spezifische Konstrukte ein, um:
- Grenzen Sie den Teil des Programms (Körper) ab, aus dem die Unterroutine ausmacht
- Zuweisen und Kennung (Name) zur Unterroutine
- Geben Sie die Namen an und Datentypen seiner Parameter und Rückgabewerte
- Einen privaten anbieten Namensspielraum für seine Temporäre Variablen
- Identifizieren Sie Variablen außerhalb der Unterroutine, die darin zugänglich sind
- Rufen Sie die Unterroutine an
- Geben Sie seinen Parametern Werte an
- Das Hauptprogramm enthält die Adresse des Unterprogramms
- Das Subprogramm enthält die Adresse der nächsten Anweisung des Funktionsaufrufs im Hauptprogramm
- Geben Sie die Rückgabewerte in seinem Körper an
- Zurückkehren zum Anrufprogramm
- Entsorgen Sie die von einem Anruf zurückgegebenen Werte
- Mit allen umgehen außergewöhnliche Bedingungen während des Anrufs getroffen
- Paket -Subroutinen in a Modul, Bibliothek, Objekt, oder Klasse
Etwas Programmiersprachen, wie zum Beispiel Pascal, Forran, Ada und viele Dialekte von BASICUnterscheiden Sie zwischen Funktionen oder Funktionsunterprogrammen, die einen expliziten Rückgabewert für das aufrufende Programm sowie Unterprogramme oder Verfahren bieten, die dies nicht tun. In diesen Sprachen sind Funktionsaufrufe normalerweise eingebettet in Ausdrücke (z. B. a sqrt
Funktion kann als als bezeichnet werden y = z + sqrt (x)
). Verfahrensaufrufe verhalten sich entweder syntaktisch als Aussagen (z. B. a drucken
Vorgehensweise kann als als bezeichnet werden Wenn x> 0 dann drucken (x)
oder werden explizit durch eine Erklärung wie z. ANRUF
oder Gosub
(z.B., Rufen Sie Print (x) an
). Andere Sprachen, wie z. C und LispelnUnterscheiden Sie nicht zwischen Funktionen und Unterroutinen.
In streng Funktionelle Programmierung Sprachen wie Haskell, Unterprogramme können keine haben Nebenwirkungen, was bedeutet, dass sich verschiedene interne Zustände des Programms nicht ändern. Funktionen geben immer das gleiche Ergebnis zurück, wenn sie wiederholt mit denselben Argumenten aufgerufen werden. Solche Sprachen unterstützen in der Regel nur Funktionen, da Unterprogramme, die keinen Wert zurückgeben, nicht verwendet werden, es sei denn, sie können einen Nebeneffekt verursachen.
Im Programmiersprachen wie zum Beispiel C, C ++, und C#, Unterprogramme können auch einfach als Funktionen bezeichnet werden (nicht mit Verwirrung mit Mathematische Funktionen oder Funktionelle Programmierung, die unterschiedliche Konzepte sind).
Eine Sprache Compiler Übersetzt in der Regel Prozeduraufrufe und kehrt in Maschinenanweisungen entsprechend einem gut definierten Rückgang zurück Konvention anrufen, damit Unterprogramme getrennt von den Programmen zusammengestellt werden, die sie nennen. Die Anweisungssequenzen, die den Anruf- und Rückgabeberechnungen entsprechen, werden als Verfahren bezeichnet Prolog und Epilog.
Vorteile
Zu den Vorteilen, ein Programm in Unterprogramme zu unterbrechen, gehören:
- Zersetzen Eine komplexe Programmieraufgabe in einfachere Schritte: Dies ist eines der beiden Hauptwerkzeuge von Strukturierte Programmierung, zusammen mit Datenstrukturen
- Reduzierung Doppelter Code Innerhalb eines Programms
- Enabling Wiederverwendung von Code über mehrere Programme hinweg hinweg
- Teilen einer großen Programmieraufgabe zwischen verschiedenen Programmierern oder verschiedenen Phasen eines Projekts
- Implementierungsdetails verstecken von Benutzern der Unterprogramme
- Verbesserung der Lesbarkeit des Codes durch Ersetzen eines Codeblocks durch einen Funktionsaufruf, bei dem a beschreibend Der Funktionsname dient dazu, den Codeblock zu beschreiben. Dies macht den Anrufcode prägnant und lesbar, auch wenn die Funktion nicht wiederverwendet werden soll.
- Verbesserung Rückverfolgbarkeit (d. h. Wenn der Code nicht in Unterprogramme zerlegt wird, wäre das Debuggen stark beeinträchtigt
Nachteile
Im Vergleich zur Verwendung von Inline-Code führt das Aufrufen einer Unterroutine einige auf Rechenaufwand im Anrufmechanismus.
Ein Unterprogramm erfordert normalerweise Standard Haushalt Code - sowohl beim Eintrag in als auch beenden von der Funktion (beenden Sie von der Funktion (Funktionsprolog und Epilog - Normalerweise sparen Allgemeine Register und minimal abgeben).
Geschichte
Die Idee eines Unterprogramms wurde ausgearbeitet, nachdem bereits seit einiger Zeit Computermaschinen existiert hatten. Die arithmetischen und bedingten Sprunganweisungen waren im Voraus geplant und haben sich relativ wenig verändert, aber die speziellen Anweisungen für Verfahrensanrufe haben sich im Laufe der Jahre stark geändert. Die frühesten Computer und Mikroprozessoren wie die Manchester Baby und die RCA 1802, hatte keine einzige Unterroutine -Anrufanweisung. Unterroutinen könnten implementiert werden, aber sie forderten Programmierer, die Anrufsequenz - eine Reihe von Anweisungen - zu verwenden, jeweils Rufseite.
Unterroutinen wurden in implementiert Konrad Zuse's Z4 1945.
1945, Alan M. Turing verwendete die Begriffe "Bury" und "Ungebur" als Mittel zur Berufung und Rückkehr von Unterroutinen.[12][13]
Im Januar 1947 präsentierte John Mauchly allgemeine Notizen auf einem "symposium digitalen Berechnungsmaschinen" im Rahmen des gemeinsamen Sponsorings der Harvard University und des Bureau of Ordnance, United States Navy. Hier diskutiert er die serielle und parallele Operation, die vorschlägt
... Die Struktur der Maschine muss ein bisschen nicht kompliziert sein. Es ist möglich, da alle logischen Eigenschaften für dieses Verfahren verfügbar sind, um einen Codierungsanweis für die Platzierung der Subroutinen an den an der Maschine bekannten Stellen zu entwickeln und so leicht in die Verwendung zu werden.
Mit anderen Worten kann man Subroutine A als Teilung und Subroutine B als komplexe Multiplikation und Unterroutine C als Bewertung eines Standardfehlers einer Abfolge von Zahlen usw. über die für ein bestimmte Problem benötigte Unterprogramme bewerten. ... Alle diese Unterprogramme werden dann in der Maschine gespeichert, und alles, was man tun muss, ist eine kurze Bezugnahme auf sie nach Nummer, wie sie in der Codierung angezeigt werden.[3]
Kay McNulty hatte eng mit John Mauchly auf der zusammengearbeitet Eniac Team und entwickelte eine Idee für Unterprogramme für die Eniac Computer Sie hat während des Zweiten Weltkriegs programmiert.[14] Sie und die anderen ENIAC -Programmierer verwendeten die Unterroutinen, um die Raketenbahnen zu berechnen.[14]
Goldstine und von Neumann schrieb ein Papier vom 16. August 1948 über die Verwendung von Unterroutinen.[15]
Einige sehr frühe Computer und Mikroprozessoren, wie die IBM 1620, das Intel 4004 und Intel 8008, und die PIC -Mikrocontroller, haben Sie einen Subroutine-Aufruf mit einem Einstruktur, der einen dedizierten Hardware-Stack zum Speichern von Rückgabedressen verwendet. Maschinen vor Mitte der 1960er Jahre-wie die Univac i, das PDP-1, und die IBM 1130- Verwenden Sie typisch a Konvention anrufen Dies spart den Anweisungszähler im ersten Speicherort der angerufenen Unterroutine. Dies ermöglicht willkürlich tiefgreifende Nistkennzeichnungen, unterstützt jedoch keine rekursiven Unterprogramme. Das PDP-11 (1970) ist einer der ersten Computer mit einem Stapel-Pushing-Unterroutine-Anrufanweis. Diese Funktion unterstützt sowohl willkürlich tiefe Unterroutine -Verschachtelung als auch rekursive Unterprogramme.[16]
Sprachunterstützung
In den sehr frühen Abgeordneten war die Unterroutineunterstützung begrenzt. Unterroutinen wurden nicht explizit voneinander oder vom Hauptprogramm getrennt, und tatsächlich könnte der Quellcode einer Unterprogramme mit dem anderer Unterprogramme durchsetzt werden. Einige Abgeordnete würden vordefiniert anbieten Makros So generieren Sie die Anrufe und Rückgabesequenzen. In den 1960er Jahren hatten die Abgeordneten in der Regel eine viel ausgefeiltere Unterstützung sowohl für Inline- als auch für separat zusammengesetzte Unterprogramme, die miteinander verbunden werden konnten.
Eine der ersten Programmiersprachen, die benutzerschriebene Unterprogramme und Funktionen unterstützen, war Forran II. Der IBM Forger II -Compiler wurde 1958 veröffentlicht. Algol 58 und andere frühe Programmiersprachen unterstützten auch die prozedurale Programmierung.
Unterroutine -Bibliotheken
Selbst mit diesem umständlichen Ansatz erwiesen sich Unterroutinen als sehr nützlich. Zum einen erlaubten sie die Verwendung des gleichen Code in vielen verschiedenen Programmen. Darüber hinaus war das Gedächtnis eine sehr knappe Ressource auf frühen Computern, und Unterprogramme ermöglichten erhebliche Einsparungen bei der Größe der Programme.
Viele frühe Computer haben die Programmanweisungen von a in den Speicher geladen geschlagenes Papierband. Jede Unterroutine kann dann durch ein separates Stück Klebeband vor oder nach dem Hauptprogramm (oder "Hauptlinie" bereitgestellt werden, die geladen oder gespleißt werden.[17]); Und das gleiche Unterroutine -Band könnte dann von vielen verschiedenen Programmen verwendet werden. Ein ähnlicher Ansatz, der auf verwendeten Computern angewendet wird geschlagene Karten für ihre Haupteingabe. Der Name Subroutine -Bibliothek Ursprünglich bedeutete ursprünglich eine Bibliothek im wörtlichen Sinne, die indizierte Sammlungen von Bändern oder Kartenabständen für die kollektive Verwendung aufbewahrte.
Rückkehr durch indirekten Sprung
Um die Notwendigkeit zu entfernen selbstmodifizierender Code, Computerdesigner lieferten schließlich eine Indirekter Sprung Anweisung, dessen Operand, anstatt das zu sein Absender selbst war der Ort einer Variablen oder Prozessorregister mit der Absenderadresse enthalten.
Auf diesen Computern würde das aufgerufene Programm die Rückgabeadresse in einer Variablen speichern, sodass das Unterprogramm beim Abschluss des Unterprogramms einen indirekten Sprung ausführen würde, der die Ausführung an den von der vordefinierten Variablen angegebenen Standort leitet.
Springe zum Unterprogramm
Ein weiterer Fortschritt war der Springe zum Unterprogramm Anweisungen, der die Einsparung der Absenderadresse mit dem Anrufsprung kombinierte und so minimiert wurde Überkopf bedeutend.
Im IBM System/360Zum Beispiel würde die Branch -Anweisungen BA oder Balr, die für das Aufrufen von Verfahren ausgelegt sind, die Absenderadresse in einem in der Anweisung angegebenen Prozessorregister durch Konvention Register 14 speichern. Um zurückzugeben, musste der Unterroutine nur einen indirekten Zweiganweis (BR) ausführen (BR ) durch dieses Register. Wenn die Unterprogramme dieses Register für einen anderen Zweck (z. B. ein anderes Unterprogramm anrufen) benötigt, speichern Sie den Inhalt des Registers in einem privaten Speicherort oder einem Register Stapel.
In Systemen wie der HP 2100, Die JSB -Anweisung würde eine ähnliche Aufgabe ausführen, außer dass die Absenderadresse am Speicherort gespeichert wurde, der das Ziel des Zweigs war. Die Ausführung des Prozedur würde tatsächlich am nächsten Speicherort beginnen. In der HP 2100 -Assemblersprache würde man zum Beispiel schreiben
... JSB Mysub (ruft Subroutine mySub.) BB ... (wird hierher zurückkehren, nachdem MySub fertig ist.)
Rufen Sie eine Unterroutine namens MySub aus dem Hauptprogramm an. Die Unterroutine würde als codiert als
Mysub NOP (Speicher für Mysubs Rückgaberadresse.) AA ... (Start von Mysubs Körper.) ... JMP MySub, ich (kehrt zum Anrufprogramm zurück.)
In der JSB -Anweisung wurde die Adresse der nächsten Anweisung (nämlich BB) in den als Operanden angegebenen Ort (nämlich MySub) eingereicht und anschließend danach an den nächsten Ort verzweigt (nämlich AA = Mysub + 1). Das Unterprogramm könnte dann zum Hauptprogramm zurückkehren, indem er den indirekten Sprung JMP MySub ausführte, der an den Ort verzweigt wurde, der am Standort MySub gespeichert war.
Compiler für FORTRAN und andere Sprachen können diese Anweisungen problemlos verwenden, sofern verfügbar. Dieser Ansatz unterstützte mehrere Anrufebene. Da jedoch der Rückgabeadresse, Parameter und Rückgabewerte einer Unterroutine feste Speicherorte zugewiesen wurden, erlaubte sie keine rekursiven Anrufe.
Übrigens wurde eine ähnliche Methode verwendet von Lotus 1-2-3In den frühen 1980er Jahren entdecken Sie die neu berechtigten Abhängigkeiten in einer Tabelle. In jeder Zelle wurde ein Ort reserviert, um die zu speichern Rückkehr die Anschrift. Seit Rundschreiben sind für natürliche Neuberechnung nicht zulässig, dies ermöglicht einen Baumweg, ohne Platz für einen Stapel im Speicher zu reservieren, was auf kleinen Computern wie die sehr begrenzt war IBM PC.
Rufen Sie Stack an
Die meisten modernen Implementierungen eines Unterroutine -Anrufs verwenden a Rufen Sie Stack an, ein Sonderfall der Stapeldatenstruktur, um Subroutine -Anrufe und -Renditen zu implementieren. Jeder Verfahrensanruf erstellt einen neuen Eintrag, der als a genannt wird Stapelrahmen, oben am Stapel; Wenn das Verfahren zurückkehrt, wird sein Stapelrahmen aus dem Stapel gelöscht und sein Platz kann für andere Verfahrensaufrufe verwendet werden. Jeder Stapelrahmen enthält die private Daten des entsprechenden Aufrufs, der typischerweise die Parameter des Prozedur und die internen Variablen sowie die Absenderadresse enthält.
Die Anrufsequenz kann durch eine Folge gewöhnlicher Anweisungen implementiert werden (ein immer noch verwendeter Ansatz in Reduziertes Anweisungssatz Computing (RISC) und Sehr langes Unterrichtswort (VLIW) Architekturen), aber viele traditionelle Maschinen, die seit den späten 1960er Jahren entworfen wurden, haben spezielle Anweisungen zu diesem Zweck enthalten.
Der Anrufstack wird normalerweise als angrenzender Speicherbereich implementiert. Es ist eine willkürliche Auswahl, ob der Boden des Stapels die niedrigste oder höchste Adresse in diesem Bereich ist, damit der Stapel im Speicher nach vorne oder rückwärts wächst. Viele Architekturen wählten jedoch das letztere.
Einige Designs, insbesondere einige Weiter Implementierungen, verwendeten zwei separate Stapel, eine hauptsächlich für Steuerungsinformationen (z. Ersteres war oder arbeitete wie ein Anrufstack und war nur indirekt über andere Sprachkonstrukte zugänglich, während letzteres direkter zugänglich war.
Als erstmals Stack-basierte Verfahrensanrufe eingeführt wurden, bestand eine wichtige Motivation darin, kostbares Gedächtnis zu retten. Mit diesem Schema muss der Compiler keinen separaten Speicherplatz im Speicher für die privaten Daten (Parameter, Rückgaberadium und lokale Variablen) jedes Prozedur reservieren. Der Stapel enthält jederzeit nur die privaten Daten der Anrufe, die derzeit vorliegen aktiv (nämlich, die genannt wurden, aber noch nicht zurückgekehrt sind). Aufgrund der Art und Weise, wie Programme normalerweise aus Bibliotheken zusammengestellt wurden, war (und ist es noch nicht ungewöhnlich), Programme zu finden, die Tausende von Unterprogrammen enthalten, von denen nur eine Handvoll zu einem bestimmten Zeitpunkt aktiv sind. Für solche Programme könnte der Call -Stack -Mechanismus erhebliche Mengen an Speicher sparen. In der Tat kann der Call -Stack -Mechanismus als die früheste und einfachste Methode für angesehen werden Automatische Speicherverwaltung.
Ein weiterer Vorteil der Call -Stack -Methode besteht jedoch darin, dass sie dies zulässt Rekursive UnterprogrammeDa jeder verschachtelte Aufruf an das gleiche Verfahren eine separate Instanz seiner privaten Daten erhält.
Verspätete Stapelung
Ein Nachteil des Call -Stack -Mechanismus sind die erhöhten Kosten eines Verfahrensanrufs und der passenden Rückgabe.[Klarstellung erforderlich] Die zusätzlichen Kosten umfassen Inkrementierung und Verringerung des Stapelzeigers (und in einigen Architekturen nach Überprüfung auf Paketüberfluss) und Zugriff auf die lokalen Variablen und Parameter nach Frame-Relativ-Adressen anstelle von absoluten Adressen. Die Kosten können in einer höheren Ausführungszeit oder einer erhöhten Prozessorkomplexität oder beidem realisiert werden.
Dieser Overhead ist am offensichtlichsten und zu beanstanden in Blattverfahren oder Blattfunktionen, die zurückkehren, ohne sich ein Verfahren anzuregen.[18][19][20] Um diesen Gemeinkosten zu reduzieren, versuchen viele moderne Compiler, die Verwendung eines Anrufstapels zu verzögern, bis er wirklich benötigt wird. Zum Beispiel der Anruf eines Prozedur P Kann die Absenderadresse und die Parameter des aufgerufenen Verfahrens in bestimmten Prozessorregistern speichern und die Kontrolle durch einen einfachen Sprung in den Körper des Verfahrens übertragen. Wenn das Verfahren P Gibt zurück, ohne einen anderen Anruf zu tätigen, der Anrufstapel wird überhaupt nicht verwendet. Wenn P muss ein anderes Verfahren anrufen QDann wird der Anrufstack verwendet, um den Inhalt aller Register (z. B. die Rückgabeadresse) zu speichern Q kehrt zurück.
Beispiele für C und C ++
In dem C und C ++ Programmiersprachen, Unterprogramme werden bezeichnet Funktionen (weiter klassifiziert als Mitgliedsfunktionen Wenn mit a verbunden Klasse, oder Kostenlose Funktionen[21] wann nicht). Diese Sprachen verwenden das spezielle Schlüsselwort Leere
Um anzuzeigen, dass eine Funktion keinen Wert zurückgibt. Beachten Sie, dass C/C ++-Funktionen Nebenwirkungen haben können, einschließlich der Änderung von Variablen, deren Adressen als Parameter übergeben werden. Beispiele:
Leere Funktion1() { / * ein Code */ }
Die Funktion gibt keinen Wert zurück und muss als eigenständige Funktion bezeichnet werden, z. B.. Funktion1 ();
int Funktion2() { Rückkehr 5; }
Diese Funktion gibt ein Ergebnis zurück (die Nummer 5), und der Aufruf kann Teil eines Ausdrucks sein, z. B.. x + function2 ()
verkohlen Funktion3(int Nummer) { verkohlen Auswahl[] = {'S', 'M', 'T', 'W', 'T', 'F', 'S'}; Rückkehr Auswahl[Nummer]; }
Diese Funktion wandelt eine Zahl zwischen 0 und 6 in den Anfangsbuchstaben des entsprechenden Wochentags um, nämlich 0 bis 's', 1 bis 'm', ..., 6 bis 's'. Das Ergebnis des Aufrufens kann einer Variablen zugeordnet werden, z. B.. num_day = function3 (number);
.
Leere Funktion4(int* pointer_to_var) { (*pointer_to_var)++; }
Diese Funktion gibt keinen Wert zurück, verändert jedoch die Variable, deren Adresse als Parameter übergeben wird. es würde mitgerufen werden mit Function4 (& variable_to_increment);
.
Kleines Basisbeispiel
Beispiel() 'Ruft die Unterroutine an Sub Beispiel 'Beginnt die Unterroutine Textwindow.Schreiben("Dies ist ein Beispiel für eine Unterroutine in Microsoft Small Basic.") 'Was die Unterroutine tut End Sub 'Beendet die Unterroutine
Im obigen Beispiel, Beispiel()
Ruft die Unterroutine an.[22] Um die tatsächliche Unterprogramme zu definieren, die Sub
Das Schlüsselwort muss verwendet werden, wobei der Unterroutine -Name folgt Sub
. Nachdem der Inhalt gefolgt ist,End Sub
muss tippt werden.
Visual Basic 6 Beispiele
In dem Visual Basic 6 Sprache, Unterprogramme werden bezeichnet Funktionen oder Subs (oder Methoden wenn mit einer Klasse verbunden). Visual Basic 6 verwendet verschiedene Begriffe genannt Typen zu definieren, was als Parameter übergeben wird. Standardmäßig ist eine nicht spezifizierte Variable als a registriert Variantentyp und kann als bestanden werden Byref (Standard) oder Byval. Wenn eine Funktion oder ein Sub deklariert wird, erhält sie eine öffentliche, private oder Freundesbezeichnung, die feststellt, ob sie außerhalb des Moduls oder Projekts zugegriffen werden kann, in dem sie deklariert wurde.
- Nach Wert [Byval] - Eine Möglichkeit, den Wert eines Arguments an ein Verfahren zu übergeben, indem eine Kopie des Wertes übergeht, anstatt die Adresse zu übergeben. Infolgedessen kann der tatsächliche Wert der Variablen nicht durch das Verfahren geändert werden, an das sie übergeben wird.
- Durch Bezugnahme [ByRef] - Eine Möglichkeit, den Wert eines Arguments an ein Verfahren zu übergeben, indem eine Adresse der Variablen übergeht, anstatt eine Kopie seines Werts zu übergeben. Dadurch kann das Verfahren auf die tatsächliche Variable zugreifen. Infolgedessen kann der tatsächliche Wert der Variablen durch das Verfahren geändert werden, an das sie übergeben wird. Sofern nicht anders angegeben, werden die Argumente mit Referenz übergeben.
- Öffentlichkeit (Optional) - Gibt an, dass die Funktionsverfahren für alle anderen Verfahren in allen Modulen zugänglich ist. Bei Verwendung in einem Modul, das eine private Option enthält, ist die Prozedur außerhalb des Projekts nicht verfügbar.
- Privatgelände (Optional) - Zeigt an, dass die Funktionsverfahren nur auf andere Verfahren im Modul zugänglich ist, in dem sie deklariert wird.
- Freund (Optional) - Nur in einem Klassenmodul verwendet. Zeigt an, dass das Funktionsverfahren während des gesamten Projekts sichtbar ist, aber für einen Controller einer Instanz eines Objekts nicht sichtbar ist.
Privatgelände Funktion Funktion1() 'Ein Code hier Ende Funktion
Die Funktion gibt keinen Wert zurück und muss als eigenständige Funktion bezeichnet werden, z. B.. Funktion1
Privatgelände Funktion Funktion2() wie Ganze Zahl Funktion2 = 5 Ende Funktion
Diese Funktion gibt ein Ergebnis zurück (die Nummer 5), und der Aufruf kann Teil eines Ausdrucks sein, z. B.. x + function2 ()
Privatgelände Funktion Funktion3(Byval intvalue wie Ganze Zahl) wie Saite Schwach Strarrray(6) wie Saite Strarrray = Array("M", "T", "W", "T", "F", "S", "S") Funktion3 = Strarrray(intvalue) Ende Funktion
Diese Funktion wandelt eine Zahl zwischen 0 und 6 in den Anfangsbuchstaben des entsprechenden Wochentags um, nämlich 0 bis 'M', 1 bis 'T', ..., 6 bis 'S'. Das Ergebnis des Aufrufens kann einer Variablen zugeordnet werden, z. B.. num_day = function3 (Nummer)
.
Privatgelände Funktion Funktion4(Byref intvalue wie Ganze Zahl) intvalue = intvalue + 1 Ende Funktion
Diese Funktion gibt keinen Wert zurück, verändert jedoch die Variable, deren Adresse als Parameter übergeben wird. es würde mit "mit" aufgerufen werden "Function4 (variable_to_increment)
".
Pl/i Beispiel
Im Pl/i Ein bezeichnetes Verfahren kann verabschiedet werden a Deskriptor Bereitstellung von Informationen über das Argument wie Stringlängen und Array -Grenzen. Auf diese Weise kann das Verfahren allgemeiner sein und die Notwendigkeit des Programmierers beseitigen, solche Informationen zu übergeben. Standardmäßig übergibt pl/ich Argumente durch Bezugnahme. Eine (triviale) Unterroutine, um das Vorzeichen jedes Elements eines zweidimensionalen Arrays zu ändern, könnte wie:
Change_Sign: Prozedur (Array); deklarieren Sie Array (*,*) float; Array = -Array; End Change_sign;
Dies könnte mit verschiedenen Arrays wie folgt aufgerufen werden:
/ * Erste Arraygrenzen von -5 bis +10 und 3 bis 9 */ deklarieren Sie Array1 (-5: 10, 3: 9) float; / * zweite Array -Grenzen von 1 bis 16 und 1 bis 16 */ deklarieren Sie Array2 (16,16) float; rufen Sie Change_Sign (Array1) auf; rufen Sie Change_Sign (Array2) auf;
Python -Beispiel
Im Python, das Schlüsselwort def
wird verwendet, um eine Funktion zu definieren. Die Aussagen, die den Körper der Funktion bilden, müssen entweder in derselben Zeile fortgesetzt oder in der nächsten Zeile beginnen und eingerückt sein.[23] Das folgende Beispielprogramm Drucke "Hallo Welt!" gefolgt von "Wikipedia" in der nächsten Zeile.
def Simple_function(): drucken('Hallo Welt!') drucken("Wikipedia") Simple_function()
Lokale Variablen, Rekursion und Wiederherstellung
Ein Unterprogramm kann es nützlich finden, eine bestimmte Menge von zu verwenden kratzen Platz; das ist, Erinnerung Wird während der Ausführung dieses Unterprogramms verwendet, um Zwischenergebnisse zu erzielen. Variablen, die in diesem Kratzbereich gespeichert sind Lokale Variablenund der Kratzerraum wird als als bezeichnet Aktivierungsdatensatz. Ein Aktivierungsdatensatz hat typischerweise a Absender Das zeigt es, wohin die Kontrolle zurückgeht, wenn das Subprogramm endet.
Ein Subprogramm kann eine beliebige Anzahl und Art von Anrufstellen haben. Wenn eine Rekursion unterstützt wird, kann sich ein Unterprogramm sogar selbst bezeichnen, was dazu führt verschachtelt Ausführung desselben Unterprogramms tritt auf. Rekursion ist ein nützliches Mittel, um einige komplexe Algorithmen zu vereinfachen und komplexe Probleme zu lösen. Rekursive Sprachen bieten im Allgemeinen eine neue Kopie lokaler Variablen für jeden Anruf. Wenn der Programmierer den Wert lokaler Variablen für die gleichen Aufrufe wünscht, können er deklariert werden statisch In einigen Sprachen oder globalen Werten oder Gemeinschaftsbereichen können verwendet werden. Hier ist ein Beispiel für eine rekursive Unterroutine in C/C ++ zu finden Fibonacci Zahlen:
int Flunkerei(int n) { wenn (n <= 1) { Rückkehr n; } Rückkehr Flunkerei(n - 1) + Flunkerei(n - 2); }
Frühe Sprachen mögen Forran Die Rekursion wurde zunächst nicht unterstützt, da Variablen statisch zugewiesen wurden, ebenso wie der Standort für die Absenderadresse. Die meisten Computer vor den späten 1960er Jahren wie die PDP-8 Hatte keine Unterstützung für Hardware -Stack -Register.
Moderne Sprachen danach Algol wie zum Beispiel Pl/i und C Verwenden Sie fast immer einen Stapel, der normalerweise von den meisten modernen Computeranweisungssätzen unterstützt wird, um für jede Ausführung eines Subprogramms einen neuen Aktivierungsdatensatz bereitzustellen. Auf diese Weise ist die verschachtelte Ausführung frei, um ihre lokalen Variablen zu ändern, ohne sich auf die Auswirkungen auf andere laufende Ausführungen auszusetzen. Wie verschachtelte Anrufe sammeln, a Rufen Sie Stack an Die Struktur wird gebildet, die aus einem Aktivierungsdatensatz für jedes suspendierte Unterprogramm besteht. Tatsächlich ist diese Stapelstruktur praktisch allgegenwärtig, und so werden Aktivierungsdatensätze üblicherweise bezeichnet Stackrahmen.
Einige Sprachen wie z. Pascal, Pl/i und Ada auch Unterstützung verschachtelte Unterprogramme, die Unterroutinen nur innerhalb der aufgerufen werden können Umfang einer äußeren (übergeordneten) Unterroutine. Innere Unterroutinen haben Zugriff auf die lokalen Variablen der äußeren Unterroutine, die sie nannte. Dies wird erreicht, indem zusätzliche Kontextinformationen innerhalb des Aktivierungsdatensatzes gespeichert werden, auch als a Anzeige.
Wenn ein Subprogramm auch dann ordnungsgemäß ausgeführt werden kann, wenn eine andere Ausführung desselben Unterprogramms bereits im Gange ist, soll dieses Subprogramm sein wieder eingetreten. Ein rekursives Subprogramm muss wieder eingetreten sein. Wiedereintrittsunterprogramme sind ebenfalls nützlich in Multi-Threaded Situationen Da mehrere Themen das gleiche Subprogramm aufrufen können, ohne sich zu stören, sich gegenseitig zu stören. In dem IBM CICs Transaktionsverarbeitungssystem, quasi-rezentrant war eine etwas weniger restriktive, aber ähnliche Anforderung für Anwendungsprogramme, die von vielen Threads geteilt wurden.
In einem Multi-Threaded Umwelt, es gibt im Allgemeinen mehr als einen Stapel. Eine Umgebung, die voll unterstützt Coroutinen oder faule Bewertung Kann andere Datenstrukturen als Stapel verwenden, um ihre Aktivierungsdatensätze zu speichern.
Überlastung
Im stark typisierte SprachenEs ist manchmal wünschenswert, eine Reihe von Funktionen mit demselben Namen zu haben, aber auf verschiedenen Datenarten oder mit unterschiedlichen Parameterprofilen zu arbeiten. Beispielsweise kann eine Quadratwurzelfunktion definiert werden, um Realitäten, komplexe Werte oder Matrizen zu betreiben. Der in jedem Fall zu verwendende Algorithmus ist unterschiedlich und das Rückgabeergebnis kann unterschiedlich sein. Durch das Schreiben von drei separaten Funktionen mit demselben Namen hat der Programmierer die Bequemlichkeit, sich nicht an verschiedene Namen für jede Art von Daten zu erinnern. Wenn ein Subtyp für die Realität definiert werden kann, um positive und negative Realität zu trennen, können zwei Funktionen für die Realität geschrieben werden, eine, um ein Real zurückzugeben, wenn der Parameter positiv ist, und ein anderer, um einen komplexen Wert zurückzugeben, wenn der Parameter ist Negativ.
Im Objekt orientierte Programmierung, Wenn eine Reihe von Funktionen mit demselben Namen unterschiedliche Parameterprofile oder Parameter verschiedener Typen akzeptieren kann, soll jede der Funktionen bezeichnet werden überladen.
Hier ist ein Beispiel für die Überlastung von Unterroutine in C ++:
#enthalten doppelt Bereich(doppelt h, doppelt w) { Rückkehr h * w; } doppelt Bereich(doppelt r) { Rückkehr r * r * 3.14; } int hauptsächlich() { doppelt Rechteck = Bereich(3, 4); doppelt circle_area = Bereich(5); std::Cout << "Bereich eines Rechtecks ist" << Rechteck << std::Endl; std::Cout << "Bereich eines Kreises ist" << circle_area << std::Endl; }
In diesem Code gibt es zwei gleichnamige Funktionen, haben jedoch unterschiedliche Parameter.
Als ein weiteres Beispiel könnte eine Unterroutine eine konstruieren Objekt Das akzeptiert Richtungen und verfolgt seinen Weg zu diesen Punkten auf dem Bildschirm. Es gibt eine Fülle von Parametern, die an den Konstruktor übergeben werden könnten (Farbe der Spur, Start-X- und Y-Koordinaten, Spurengeschwindigkeit). Wenn der Programmierer wollte, dass der Konstruktor nur den Farbparameter akzeptieren kann, kann er einen anderen Konstruktor aufrufen, der nur Farbe akzeptiert, was wiederum den Konstruktor mit allen Parametern aufruft Standardwerte Für alle anderen Parameter (x und y würden im Allgemeinen auf dem Bildschirm zentriert oder im Ursprung platziert, und die Geschwindigkeit würde auf einen anderen Wert der Wahl des Codierers eingestellt).
Pl/ich hat das GENERISCH
Attribut zum Definieren eines generischen Namens für eine Reihe von Eintragsreferenzen, die mit verschiedenen Argumentypen aufgerufen werden. Beispiel:
Deklarieren gene_name generic (name wenn (binary behoben), flame wenn (float), pathname sonst);
Für jeden Eintrag können mehrere Argumentdefinitionen angegeben werden. Ein Aufruf von "Gen_Name" führt zu einem Aufruf zum "Namen", wenn das Argument binär festgelegt ist, "Flame", wenn float "usw. Wenn das Argument nicht der Entscheidungen entspricht, wird" Pathname "aufgerufen.
Schließungen
A Schließung ist ein Subprogramm zusammen mit den Werten einiger seiner Variablen aus der Umgebung, in der es geschaffen wurde. Verschlüsse waren ein bemerkenswertes Merkmal der LISP -Programmiersprache, die von vorgestellt wurde John McCarthy. Abhängig von der Implementierung können Schließungen als Mechanismus für Nebenwirkungen dienen.
Konventionen
Es wurden eine große Anzahl von Konventionen für die Kodierung von Unterprogrammen entwickelt. In Bezug auf ihre Benennung haben viele Entwickler den Ansatz übernommen, dass der Name eines Unterprogramms a sein sollte Verb Wenn es eine bestimmte Aufgabe erledigt, und Adjektiv Wenn es eine Anfrage macht und a Substantiv Wenn es verwendet wird, um Variablen zu ersetzen.
Einige Programmierer schlagen vor, dass eine Unterroutine nur eine Aufgabe ausführen sollte, und wenn eine Unterroutine mehr als eine Aufgabe ausführt, sollte sie in mehr Unterroutinen aufgeteilt werden. Sie argumentieren, dass Unterroutinen Schlüsselkomponenten in sind Code -Wartungund ihre Rollen im Programm müssen unterschiedlich bleiben.
Befürworter von Modulare Programmierung (Modularisierung des Codes) Befürworte, dass jede Unterroutine eine minimale Abhängigkeit von anderen Code -Teilen haben sollte. Zum Beispiel die Verwendung von globale Variablen wird im Allgemeinen von Anwälten für diese Perspektive als unklug angesehen, da sie eine enge Kopplung zwischen der Unterroutine und diesen globalen Variablen hinzufügt. Wenn eine solche Kopplung nicht erforderlich ist, ist ihr Rat dazu Refaktor Unterroutinen zu akzeptieren bestanden Parameter stattdessen. Eine Erhöhung der Anzahl der an Unterprogramme übergebenen Parameter kann jedoch die Code -Lesbarkeit beeinflussen.
Rückgabecodes
Außerdem hauptsächlich oder normal Effekt muss ein Unterprogramm möglicherweise das aufrufende Programm darüber informieren außergewöhnlich Bedingungen, die möglicherweise während der Ausführung aufgetreten sind. In einigen Sprachen und Programmierstandards erfolgt dies oft durch a Rückgabe Code, ein ganzzahliger Wert, der vom Unterroutine an einem Standardort platziert wird und die normalen und außergewöhnlichen Bedingungen codiert.
In dem IBM System/360, wo der Rückgabercode von der Unterroutine erwartet wurde, wurde der Rückgabewert häufig als vielfältiges von 4 ausgelegt - damit er als direkte verwendet werden kann Zweigtisch Index in eine Zweigentabelle, die sich häufig unmittelbar nach dem Anrufbefehl befindet, um zusätzliche bedingte Tests zu vermeiden, wodurch die Effizienz weiter verbessert wird. In dem System/360 Montagesprache, man würde zum Beispiel schreiben:
BAL 14, SUBRTN01 Gehen Sie zu einer Unterroutine und speichern Sie die Rückgabeadresse in R14 B Tabelle (15) Verwenden Sie den zurückgegebenen Wert in Reg 15, um die Zweigentabelle * zu indexieren, * Verzweigungen an den entsprechenden Zweiginstrument. Tabelle B OK Returncode = 00 Good} B schlechter Rückgabecode = 04 Ungültige Eingabe} Zweig Tabelle B Fehler zurücksend
Optimierung von Unterroutine -Anrufen
Es gibt eine bedeutende Laufzeit Überkopf Bei der Aufruf eines Unterprogramms, einschließlich der Übergabe der Argumente, der Verzweigungen an das Subprogramm und Verzweigungen an den Anrufer. Der Overhead beinhaltet häufig das Speichern und Wiederherstellen bestimmter Prozessorregister, die Zuordnung und Rückgewinnung von Anrufrahmenspeichern usw.[Beispiel erforderlich] In einigen Sprachen impliziert jeder Subroutine -Aufruf auch automatische Tests des Rückgabescode des Unterroutins oder der Handhabung von Ausnahmen Das kann es erhöhen. Eine signifikante Überkopfquelle in objektorientierten Sprachen ist die intensiv verwendete Dynamischer Versand für Methodenaufrufe.
Es gibt einige scheinbar offensichtliche Optimierungen von Verfahrensaufrufen, die nicht angewendet werden können, wenn die Verfahren Nebenwirkungen haben können. Zum Beispiel im Ausdruck (f (x) -1)/(f (x) +1)
, die Funktion f
muss zweimal aufgerufen werden, da die beiden Anrufe unterschiedliche Ergebnisse zurückgeben können. Darüber hinaus der Wert von x
Muss vor dem zweiten Anruf erneut abgerufen werden, da der erste Anruf möglicherweise geändert wurde. Die Bestimmung, ob ein Unterprogramm einen Nebeneffekt haben kann, ist sehr schwierig (in der Tat,, unentscheidbar aufgrund Reis Satz). Während diese Optimierungen in rein funktionalen Programmiersprachen sicher sind, müssen Compiler typischer imperativer Programmierung normalerweise das Schlimmste annehmen.
Einbindung
Eine Methode zur Beseitigung dieses Overheads ist Inline -Expansion oder Einbindung des Körper des Unterprogramms an jedem Rufseite (gegen die Abzweigung an der Unterroutine und im Rücken). Dies vermeidet nicht nur den Anrufaufwand, sondern erlaubt auch die Compiler zu optimieren das Verfahren des Verfahrens Karosserie Effektiver durch Berücksichtigung des Kontextes und der Argumente bei diesem Anruf. Der eingefügte Körper kann vom Compiler optimiert werden. Das Inlining erhöht jedoch in der Regel die Codegröße, es sei denn, das Programm enthält nur einen Aufruf an die Unterroutine.
Siehe auch
- Funktion (Mathematik)
- Methode (Computerprogrammierung)
- Integrierte Funktion
- Bewertungsstrategie
- Modulare Programmierung
- Transclusion
- Bedienerüberlastung
- Schutzverfahren
- Funktionelle Programmierung
- Befehlsland -Trennung (CQS)
- Coroutinen, Unterprogramme, die sich gegenseitig anrufen, als ob beide die Hauptprogramme wären
- Event -Handler, ein Subprogramm, das als Reaktion auf ein Eingabeereignis aufgerufen wird oder unterbrechen
- Asynchroner Verfahrensanruf, ein Subprogramm, das nach seinen Parametern aufgerufen wird, werden von anderen Aktivitäten festgelegt
Verweise
- ^ US -Wahlhilfekommission (2007). "Definitionen von Wörtern mit besonderen Bedeutungen". Leitlinien für freiwillige Abstimmungssysteme. Archiviert von das Original Am 8. Dezember 2012. Abgerufen 14. Januar 2013.
- ^ Subrata Dasgupta (7. Januar 2014). Es begann mit Babbage: Die Entstehung der Informatik.Oxford University Press.S. 155–. ISBN 978-0-19-930943-6.
- ^ a b J.W. Mauchly, "Vorbereitung von Problemen für Maschinen vom Typ EDVAC" (1947), in Brian Randell (Hrsg.), The Origins of Digital Computers, Springer, 1982.
- ^ Wheeler, D. J. (1952). "Die Verwendung von Unterroutinen in Programmen" (PDF). Verfahren des ACM National Meeting von 1952 (Pittsburgh) auf - ACM '52. p. 235. doi:10.1145/609784.609816.
- ^ Wilkes, M. V.; Wheeler, D. J.; Gill, S. (1951). Vorbereitung von Programmen für einen elektronischen digitalen Computer. Addison-Wesley.
- ^ Dainith, John (2004). ""Offene Unterroutine." Ein Wörterbuch des Computers ". Encyclopedia.com. Abgerufen 14. Januar 2013.
- ^ Turing, Alan M. (1945), Bericht von Dr. A.M. Vorschläge für die Entwicklung einer automatischen Computing -Engine (ACE): beim Exekutivkomitee des NPL im Februar 1946 vorgelegt nachgedruckt Copeland, B. J., ed. (2005). Alan Turings automatische Computing -Engine. Oxford: Oxford University Press. p. 383. ISBN 0-19-856593-3.
- ^ Donald E. Knuth (1997). Die Kunst der Computerprogrammierung, Band I: Grundalgorithmen. Addison-Wesley. ISBN 0-201-89683-4.
- ^ O.-J. Dahl; E. W. Dijkstra; C. A. R. Hoare (1972). Strukturierte Programmierung. Akademische Presse. ISBN 0-12-200550-3.
- ^ Wilson, Leslie B. (2001). Vergleichende Programmiersprachen, dritte Ausgabe. Addison-Wesley. p. 140. ISBN 0-201-71012-9.
- ^ Stroustrup, Bjarne (2013). Die C ++ - Programmiersprache, vierte Ausgabe. Addison-Wesley. p. 307. ISBN 978-0-321-56384-2.
- ^ Turing, Alan Mathison (19. März 1946) [1945], Entwicklungsvorschläge in der Mathematikabteilung einer automatischen Computermotor (ACE) (NB. Vor dem Exekutivkomitee des National Physical Laboratory (Großbritannien) vorgestellt.)
- ^ Zimmermann, Brian Edward; Doran, Robert William (1. Januar 1977) [Oktober 1975]. "Die andere Turing -Maschine". Das Computerjournal. 20 (3): 269–279. doi:10.1093/comjnl/20.3.269. (11 Seiten)
- ^ a b Isaacson, Walter (18. September 2014). "Walter Isaacson über die Frauen von Eniac". Reichtum. Archiviert von das Original am 12. Dezember 2018. Abgerufen 14. Dezember 2018.
- ^ Planung und Codierung von Problemen für ein elektronisches Computerinstrument, Pt 2, vol. 3 https://library.ia.edu/files/pdfs/ecp/planningcodingof0103inst.pdf (Siehe S. 163 des PDF für die entsprechende Seite)
- ^ Guy Lewis Steele Jr. KI -Memo 443."Den" teuren Verfahren "Mythos entlarven; oder Verfahrensanruf -Implementierungen als schädlich. “. Abschnitt "C. Warum Verfahrensanrufe einen schlechten Ruf haben".
- ^ Frank, Thomas S. (1983). Einführung in die PDP-11 und seine Montagesprache. Prentice-Hall-Software-Serie. Prentice-Hall. p. 195. ISBN 9780134917047. Abgerufen 6. Juli 2016.
Wir könnten unseren montierenden Angestellten mit Kopien des Quellcode für alle unsere nützlichen Unterprogramme liefern. Wenn Sie ihm dann ein Hauptprogramm für die Versammlung präsentieren, sagen Sie ihm, welche Unterprogramme in der Hauptlinie genannt werden [...]
- ^ "Arm Information Center". Infocenter.arm.com. Abgerufen 29. September 2013.
- ^ "X64 Stack -Nutzung". Microsoft Docs. Microsoft. Abgerufen 5. August 2019.
- ^ "Funktionstypen". Msdn.microsoft.com. Abgerufen 29. September 2013.
- ^ "Was ist mit einer freien Funktion gemeint".
- ^ "Microsoft Small Basic". www.smallbasic.com.
- ^ "4. Mehr Steuerflusswerkzeuge - Python 3.9.7 Dokumentation".