Matthias Reitinger
ɐɯıǝɹ
Das stimmt nicht uneingeschränkt. Es gibt eine Vielzahl von Aufrufkonventionen. Bei einigen muss der aufrufende Programmteil den Stack aufräumen, bei anderen erledigt das das aufgerufene Unterprogramm. Auch müssen Parameter nicht immer über den Stack übergeben werden, man kann dazu z.B. auch die CPU-Register verwenden. Die meisten Compiler für die x86-Architektur übergeben den Rückgabewert einer Funktion beispielsweise über das EAX-Register.Beim Aufrufen einer Funktion werden immer als erstes die Parameter auf den Stack gepusht; diese Arbeit erledigt stets das aufrufende Programm. Das gilt auch für das Zurückliefern des Funktionsaufrufes, der durch das aufrufende Programm vom Stack gepopt wird.
Nein. Wie die Funktion aufzurufen ist, bestimmt schon der Zeigertyp. Der Zeiger verweist lediglich auf den Einsprungspunkt der Funktion.Der Zeiger verseist im wesentlichen auf die Informationen, wie diese Funktion aufzurufen ist, ob über ein zu ladendes Modul oder, bei selbst geschriebenen Funktionen, direkt in den Code des laufenden Programms.
Doch, bei Funktionszeigern findet im Allgemeinen eine zusätzliche Dereferenzierung statt. Eine normaler Funktionsaufruf (ohne Funktionszeiger) entspricht einem Sprung an eine feste Adresse im Speicherbereich des Programms. Diese ermittelt der Linker zur Kompilierzeit und trägt sie an den entsprechenden Stellen ein. Dagegen steht die Adresse, auf die ein Funktionszeiger verweist, erst zur Laufzeit fest. Das Programm muss also zuerst diese Adresse auslesen und kann erst dann den Sprung ausführen.Deswegen ist der Ablauf beim Aufruf einer Funktion immer der gleiche, egal, ob du die Funktion über einen Funktionszeiger oder über den 'Original'-Namen aufrufst; eine zusätzliche Dereferenzierung findet nicht statt.
Grüße,
Matthias