Loading AI tools
Teil eines Computerprogramms, der aus anderen Programmteilen oder Programmen aufgerufen werden kann Aus Wikipedia, der freien Enzyklopädie
Ein Unterprogramm ist ein Teil eines Computerprogramms, das eine bestimmte Funktionalität bereitstellt. Es kann von anderen Programmen/Programmteilen aufgerufen werden, um eine Aufgabe zu übernehmen und verzweigt danach wieder an die aufrufende Stelle zurück. Ein Unterprogramm wird i. d. R. durch einen Bezeichner (z. B. einen Namen) identifiziert, und ihm können zur Verarbeitung Daten als Argumente übergeben werden.[1]
Bezüglich der Terminologie kennt man aus der Praxis einen großen Reichtum an Varianten, die teilweise synonym, teilweise mit semantischen Unterschieden angewendet werden.[1] Bezeichnungen wie Prozedur (procedure), Funktion (function), Routine oder Subroutine, Operation, Section, Modul sind teils historisch und oft im Umfeld verschiedener Programmiersprachen entstanden, entsprechen aber im Wesentlichen der Bedeutung ‚Unterprogramm‘ oder werden so genannt. So sind im Kontext der objektorientierten Programmierung Methoden (methods) – je nach Programmiersprache – einer Klasse, einem Objekt oder einer generischen Funktion als in sich abgeschlossene Einheiten zugeordnet.
Bezüglich der Erstellung, Wartung und Ausführung können Unterprogramme je nach Art der Implementierung eigenständige Komponenten sein (‚Unterprogramme‘ im engeren Sinn, die oft vorübersetzt in Programmbibliotheken zusammengefasst sind) oder, zusammen mit anderen Funktionsteilen, den Programmcode eines bestimmten Programms bilden.
Das Kapseln von Programmteilen in Unterprogrammen entspringt dem Paradigma der prozeduralen Programmierung. Die beiden wichtigsten Vorteile, die dadurch beim Softwaredesign erzielt werden, sind die Wiederverwendbarkeit von Programmteilen und die Verbesserung der Verständlichkeit und Wartbarkeit des Quelltexts.
Unterprogramme für bestimmte technische oder betriebliche Funktionen (z. B. eine Prüfziffernberechnung) als unternehmensweiter Standard sind ein Aspekt der Softwarearchitektur.
Eine Weiterführung des Konzepts der Unterprogramme sind die modulare Programmierung und Software-Module.
David Wheeler, Maurice V. Wilkes und Stanley Gill gelten als Entwickler der ersten Subroutine (damals auch Wheeler-jump genannt).[3][4][5][6]
In frühen imperativen Programmiersprachen (zum Beispiel frühe BASIC- und FORTRAN-Varianten) gab es nur das Konzept des parameterlosen Unterprogramms, welches über Sprunganweisungen aufgerufen wurde und ausschließlich über globale Variablen mit dem Hauptprogramm wechselwirken konnte.
Mit dem Aufkommen der strukturierten Programmierung entwickelte sich das Konzept der Prozedur mit Aufrufparametern, die zunächst überwiegend als Referenzparameter übergeben wurden (call by reference), das heißt eine Änderung des Parameters innerhalb der Prozedur ändert den zugehörigen Parameter an der Aufrufstelle der Prozedur. Die Einführung von expliziten Rückgabewerten von Prozeduren (respektive Funktionen) ermöglichte die Berechnung von Resultaten, ohne die Referenzparameter zu verändern.
In einem weiteren Schritt wurden Wertparameter zur Übergabe an Prozeduren eingeführt (call by value), um unerwünschte Rückwirkungen auf das Hauptprogramm weiter zu reduzieren.
Zur Vermeidung von Programmfehlern wurde in einigen Programmiersprachen wie zum Beispiel Pascal eine starke Typisierung von Parametern eingeführt: die tatsächlich verwendeten Parameter müssen hierbei relativ streng zuweisungskompatibel mit den formal deklarierten Parametern sein.
In manchen Programmiersprachen, wie beispielsweise Modula-2, können Prozedurvariablen aufgerufen oder als Parameter eingesetzt werden.
Schließlich wurden Prozeduren als objektbezogene Methoden oder Zugriffsfunktionen Bestandteil des objektorientierten Paradigmas, etwa in den Programmiersprachen Java und C++.
Unterprogramme können, abhängig von der verwendeten Entwicklungsumgebung oder Programmiersprache, unterschiedlich implementiert sein:
Innerhalb dieser Grundvarianten stellen bestimmte Programmiersprachen weitere Funktionsdetails bereit, die beim Binden und Laden von Unterprogrammen anwendbar sind. Siehe dazu die Beispiele zu Überladen oder Überschreiben.
Eine besondere Kategorie von Unterprogrammen bilden die in einem Computersystem bereitgestellten Systemfunktionen (wie Lesen, Schreiben, Clock usw.). Sie werden im engeren Sinn nicht als Unterprogramm bezeichnet, jedoch nach demselben Ablaufprinzip benutzt: Aufruf mittels Anweisung, meist mit Parameter-/Argumentenübergabe, Ausführung der Subfunktion zum Beispiel im Betriebssystem, anschließend Rückkehr ins rufende Programm mit Fortsetzung der Verarbeitung.
Die Beispiele in den Programmiersprachen C, C++ und Java zeigen Details zur Programmierung mit Unterprogrammen.
Das folgende Beispiel ist ein in Unterprogramm in C, C++ oder Java, das beim Aufruf einen Wert entgegennimmt und ihn mit einem konstanten Wert multipliziert, es soll die Umrechnung von Zoll in Zentimeter demonstrieren.
float inch2cm(float length) {
return 2.54 * length;
}
Das folgende Beispiel in Python gibt die in message
übergebene Zeichenkette auf dem Bildschirm aus, liefert aber keinen Wert zurück.
def hello(message):
print(message)
Ein einfaches Hallo-Welt-Programm in Assemblersprache, die vier Zeilen ab der Marke print
stellen das Unterprogramm dar.
segment code
..start:
mov ax, data
mov ds, ax
call print ; Aufruf des Unterprogramms
mov ah, 4Ch
int 21h ; Beenden des Programms
print:
mov dx, hello
mov ah, 09h
int 21h
ret
segment data
hello: db 'Hello World!', 13, 10, '$'
Wie und mit welchen Aufrufkonventionen aufrufende und aufgerufene Module zusammenwirken, zeigt das nachfolgende Beispiel. Unterstellt sei ein fiktives Hauptprogramm, das ein Unterprogramm mit Namen UPRO aufruft. Siehe auch nebenstehende Grafik:
* Daten: A. >Struktur von A, z. B.: Ax >Format und Längen Ay ... B. B1 (Definitionen, ggf. weitere Teilfelder) B2 (Definitionen) B3 (Definitionen) * Funktionscode: A-ROUTINE. A-1. >Befehle-1 Call UPRO Using A, B2. A-2. >Befehle-2, z. B. Auswerten und Verarbeiten Rückgabewert(e) A-ROUTINE Exit. >beliebige weitere Routinen/Befehle * Programm-Ende
* Datendefinitionen: A-DAT >Format und Sub-Struktur wie in A; andere Bezeichner möglich! B-2 dto. C-x z. B. eigene Definitionen von UPRO * Funktionscode: Entry UPRO Using A-DAT, B-2. >Feldbezeichnungen von Using ggf. abweichend, Reihenfolge identisch zu 'Call'! >Weitere Befehle des Unterprogramms: >Mit vollem Zugriff (auch ändernd) auf die Struktur (Einzelfelder) von A-Daten und B2. Ggf. setzen Returncode, z. B. in B-2 (= B2) Exit = UPRO-Ende
* Call im rufenden Programm: Setzt in einer (vom Compiler angelegten) Hauptspeicher-Adressliste mit 2 Einträgen die Adresse von A und von B-2 Setzt einen Zeiger (Register, konkret R1) auf die Adressliste Setzt einen Zeiger (Register 14) auf die Rückkehradresse A-2. Setzt einen Zeiger (Register 13) auf die Register-Savearea, (Speicherbereich automatisch vom Compiler reserviert, Details siehe[7]) Lädt Register 15 mit der Adresse (Entrypoint) des Unterprogramms (die z. B. vom Linkage Editor im Maschinenprogramm eingesetzt wurde) Verzweigt über R15 in das Unterprogramm * Entry im Unterprogramm: >Sichern der Registerstände in die Savearea des rufenden Programms (lt. R13) Speichern der Adresse dieser Savearea (= Inhalt R13) in einem eigenen Speicherbereich >Übernehmen der übergebenen Variablen (aus Adressliste lt. R1): Adr(A-DAT) = aus Adressliste(1. Adresse), Adr(B-2) = aus Adressliste(2. Adresse) >Verarbeitung – mit Zugriff auf übergebene und eigene Daten sowie individueller Registernutzung * Rücksprung ins rufende Programm: >Laden R13 mit der gespeicherten Adresse der Savearea Rückladen aller Register aus der Savearea lt. R13 >Exit: Verzweigung (= Rückkehr) zu Adresse A-2 im rufenden Programm (lt. Inhalt R14)
Nach demselben Schema (Registerkonventionen, Savearea) könnte das Modul weitere Untermodule aufrufen. Das dazu erforderliche Sichern der Registerstände zum Zeitpunkt des Aufrufs erfolgt jeweils in einer „Savearea“ genannten Speicherstruktur aufrufender Module, die folgenden Aufbau aufweist:
|_A_|_B_|_C_|_D1_|_D2_|_.._|_D15_| = 18 „Fullwords“ (je 4 Bytes) = 72 Bytes A = nicht belegt, reserviert B = Adresse der Savearea des aufrufenden Moduls; vom aufgerufenen Modul in seiner eigenen Savearea gesetzt C = Adresse der Savearea des aufgerufenen Moduls; vom aufgerufenen Modul in der Savearea des aufrufenden Moduls gesetzt Dn = Inhalt der Register „14 bis 12“ (entspricht R14,R15,R0,R1 .. R12): vom aufgerufenen Modul in der Savearea des aufrufenden Moduls gespeichert und vor dem Rücksprung zurückgeladen.
Über die Inhalte von Speicherstelle B und C sind die Saveareas der beteiligten Module in ihrer Aufrufreihenfolge miteinander verkettet; sie zeigen den Stand des jeweils letzten Modulaufrufs, womit sich z. B. im Debug-Modus bei Modultests die Aufruftiefe und die -Reihenfolge ermitteln und nachvollziehen lässt. Einen detaillierten Assembler-Programmcode für die Savearea-Behandlung zeigt dieses Beispiel.
Unterprogramme (UP) führen Funktionen aus, die in der Regel Daten benötigen, die zu den sie aufrufenden Programmen gehören. Aus Sicht des Unterprogramms können diese Daten Eingangs- oder Ergebniswerte sein. Da je nach angewendeter Unterprogrammtechnik ein Unterprogramm grundsätzlich nur ‚Zugriff‘ auf seine eigenen Daten hat, enthalten die Programmiertechniken und -Sprachen Mechanismen, mit denen die ‚fremden‘ Daten für das Unterprogramm verfügbar gemacht werden; nur dann können dessen Befehle die für sie ‚externen‘ Daten ansprechen. Je nach UP-Variante/Programmiersprache können diesbezüglich verschiedene Konstellationen unterschieden werden:
Die Parametertechnik wird vor allem bei unabhängig vom aufrufenden Programm entwickelten Unterprogrammen verwendet, um einem aufzurufenden UP mitzuteilen, welche Daten es verwenden/verarbeiten soll. Diese Parameter bilden die gemeinsame Schnittstelle zwischen aufrufendem und aufzurufendem UP. Ein Beispiel ist „DispoSaldoPrüfen (Kontonummer, Betrag, Antwort)“. Im Unter- und im Hauptprogramm sind diese Angaben nach einheitlich angewendeten Konventionen strukturell identisch zu deklarieren. Die während der Programmausführung beim einzelnen Aufruf tatsächlich übergebenen Werte werden 'Argumente' genannt, z. B. als Kontonummer der Wert '4711' und als Betrag '-500,00', als Antwort könnte alternativ 'OK' oder 'Überziehung' zurückgeliefert werden. Dieses Begriffspaar (Parameter und Argument) wird synonym auch als formale und tatsächliche Parameter bezeichnet.
Parameter/Argumente können elementare Datenfelder beliebigen Formats sein, z. B. Text oder Integer – oder auf beiden Seiten der Schnittstelle einheitlich definierte Datenstrukturen. Bezüglich der Verwendbarkeit der übergebenen Daten kann unterschieden werden, ob diese nur gelesen oder auch verändert werden können, zum Beispiel für Ergebniswerte. Weiterhin lässt sich unterscheiden, ob mit den Parametern Adressen (im Hauptspeicher) oder die tatsächlichen Daten übergeben werden.
Technisch (z. B. im Maschinencode) erfolgt die Übergabe der Parameter/Argumente je nach verwendeter Programmiersprache und Rechnertechnologie mithilfe unterschiedlicher Hardware-Einrichtungen. So kann z. B. der Stack die Argumente aufnehmen oder Parameter werden über Register übergeben.
Seamless Wikipedia browsing. On steroids.
Every time you click a link to Wikipedia, Wiktionary or Wikiquote in your browser's search results, it will show the modern Wikiwand interface.
Wikiwand extension is a five stars, simple, with minimum permission required to keep your browsing private, safe and transparent.