„Wenn ein Arbeiter seine Arbeit gut machen will, muss er zuerst seine Werkzeuge schärfen.“ – Konfuzius, „Die Gespräche des Konfuzius. Lu Linggong“
Titelseite > Programmierung > Inline-Funktionen in C und C++

Inline-Funktionen in C und C++

Veröffentlicht am 08.11.2024
Durchsuche:157

Inline Functions in C and C

Einführung

C hat das Inline-Schlüsselwort hinzugefügt, das einer Funktionsdefinition vorangestellt werden kann, wie zum Beispiel:

inline int max_int( int a, int b ) {
    return a > b ? a : b;
}

um dem Compiler einen „Hinweis“ zu geben, dass das Programm insgesamt von der Leistung profitieren könnte, wenn die Funktion inlined ist.

Bei einer Funktion, die inlined wurde, wurde der Code an jedem Punkt, an dem sie aufgerufen wurde, erweitert, anstatt den normalen Funktionsaufrufmechanismus wie folgt auszuführen:

  • Register werden gespeichert.
  • Argumentwerte auf den Stapel verschieben.
  • Die Aufrufanweisung wird ausgeführt.
  • Die Funktion, die schließlich die ret-Anweisung ausführt.
  • Register werden wiederhergestellt.

Für sehr kleine Funktionen kann Inlining zu einer Leistungssteigerung führen. Aber wie bei fast allem anderen gibt es auch hier Kompromisse.

Das Inline-Schlüsselwort wurde auf C99 zurückportiert, jedoch mit etwas anderen Anforderungen – mehr später.

Unterschiede zu Makros

Inline-Funktionen sind wie funktionsähnliche Makros (und sollen viele ihrer Anwendungen ersetzen). Im Allgemeinen ist dies eine gute Sache, denn Inline-Funktionen sind Funktionen und verfügen über eine vollständige Funktionssemantik und nicht nur über eine bloße Textersetzung durch den Präprozessor, der weder C noch C versteht.

Ein naiv äquivalentes Makro zur Funktion max_int():

#define MAX_INT(A,B)  A > B ? A : B  /* bad implementation */

hat die folgenden Probleme:

  • Erweiterte Argumente, z. B. MAX(n & 0xFF, 8), können zu einer falschen Operatorpriorität führen.
  • Argumente mit Nebenwirkungen, z. B. MAX(n , 8), können mehrere Nebenwirkungen haben.
  • Es gibt keine Typprüfung der Argumente bei der Definition.
  • Fehler sind oft ausführlich und schwer zu lesen.

Zusätzlich ein Makro:

  • Kann sein Argument ändern (das ist oft nicht das, was Sie wollen).

Inline-Funktionen weisen keines dieser Probleme auf, können jedoch den gleichen Leistungsvorteil erzielen. Verwenden Sie daher Inline-Funktionen anstelle von funktionsähnlichen Makros.

Nur ein Hinweis

Wie bereits erwähnt, ist die Angabe von „inline“ nur ein „Hinweis“ für den Compiler, dass das Programm insgesamt von der Inline-Funktion profitieren könnte. Dem Compiler steht es frei, den Hinweis zu ignorieren.

Warum? Denn es gibt Fälle, in denen es entweder keine gute Idee oder unmöglich ist. Eine Funktion ist entweder nicht inline oder normalerweise nicht inline, wenn eine der folgenden Bedingungen zutrifft:

  • Die Funktion ist „zu groß.“
  • Sie rufen die Funktion über einen Zeiger auf die Funktion auf.
  • Die Funktion ist rekursiv.
  • Die Funktion hat eine Schleife.

Es kann andere Gründe geben. Es hängt alles stark von der Funktion, ihren Argumenten, dem Compiler und den ihr zugewiesenen Optionen ab.

Wenn der Compiler eine Funktion nicht inline einbinden kann oder möchte, wird er Sie nicht warnen, dass er dies nicht getan hat (standardmäßig). Einige Compiler, z. B. gcc, verfügen über eine -Winline-Option, die Sie warnt und Ihnen den Grund angibt, warum eine Funktion nicht eingebunden wurde.

Die Angabe von „inline“ ähnelt der Angabe von „register“ in älterem Code – beides sind nur Hinweise.

Wann (und wann nicht) für Inline

Bei den meisten Funktionen liegt der Großteil der Kosten für die Ausführung der Funktion im Funktionskörper und nicht im Funktionsaufrufmechanismus. Damit eine Funktion ein guter Kandidat für Inlining ist, muss sie im Allgemeinen wie folgt lauten:

  • Klein genug, damit die Kosten des Funktionsaufrufmechanismus dominieren.
  • Wird an Orten verwendet, an denen es tatsächlich auf die Leistung ankommt, z. B. in engen Schleifen.

Im Zweifelsfall profilieren Sie Ihren Code. Die Verwendung von Inline ist kein ein magisches „Mach mich schneller“-Schlüsselwort. Darüber hinaus kann die übermäßige Verwendung von Inline zu einer Code-Aufblähung führen, die die Leistung Ihres Programms insgesamt schlechter macht.

Weitere Informationen finden Sie unter Die Inline-Krankheit.

Zu den Funktionen, die häufig gute Kandidaten für das Inlining sind, gehören:

  • „Einzeiler“ wie „Getter“ und „Setter“.
  • Einfache Wrapper um Aufrufe anderer Funktionen, die bestimmte Werte für Argumente bereitstellen oder Umwandlungen durchführen.

Eine ideale Inline-Funktion sowohl erhöht die Leistung und verringert die Codegröße.

Eine Einschränkung für jede Inline-Funktion besteht jedoch darin, dass bei einer Änderung ihrer Definition der gesamte Code, der sie verwendet, neu kompiliert werden muss.

Inline-Optimierungen

Wenn eine Inline-Funktion tatsächlich vom Compiler eingebunden wird, kann der Compiler zusätzlich zum Weglassen des Codes für den normalen Funktionsaufrufmechanismus möglicherweise auch Folgendes tun:

  • Entfernen Sie ein oder mehrere Funktionsargumente vollständig, deren Werte Konstanten sind, durch sofortige Adressierung.
  • Führen Sie bessere Optimierungen durch, die sich über den Code erstrecken, in den die Funktion eingebunden ist, was normalerweise nicht über Funktionsgrenzen hinweg möglich wäre.

Inline-Funktionsdefinition

Damit der Compiler eine Funktion einbinden kann, muss er ihre Definition (nicht nur ihre Deklaration) in jeder .c- oder .cpp-Datei, in der sie verwendet wird, „sehen“ können genau wie ein Makro. Daher muss eine Inline-Funktion in einer Header-Datei definiert sein.

Normalerweise muss eine Funktion, wie alles andere auch,

genau eine Definition haben, indem die One Definition Rule (ODR) eingehalten wird. Da die Definition einer Inline-Funktion jedoch in mehreren .c- oder .cpp-Dateien „gesehen“ wird, wird der ODR für diese Funktion ausgesetzt.

Es ist möglich, unterschiedliche Definitionen für Inline-Funktionen mit demselben Namen zu haben, aber dies führt zu undefiniertem Verhalten, da der Compiler keine Möglichkeit hat, zu überprüfen, ob alle Definitionen gleich sind.

Um eine Funktion in C zu integrieren, müssen Sie der Funktionsdefinition lediglich „inline“ voranstellen – fertig. Der Compiler und/oder Linker verwirft für Sie automatisch alle Definitionen bis auf eine aus der endgültigen ausführbaren Datei.

Um jedoch eine Funktion in C zu integrieren, müssen Sie dem Compiler zusätzlich

explizit mitteilen, in welche .o-Datei die eine Definition eingefügt werden soll, falls der Compiler entweder nicht in der Lage oder nicht bereit ist, eine Funktion über zu integrieren extern inline.

Zum Beispiel würden Sie in

genau einer .c-Datei eine Funktion deklarieren wie:

// util.c extern inline int max_int( int, int );
// util.c
extern inline int max_int( int, int );
Das weist den Compiler an, „die eine Definition für max_int() in util.o einzufügen.“

Alternativ können Sie in C auch eine statische Inline-Funktion deklarieren:


static inline int max_int( int a, int b ) { a > b zurückgeben? a : b; }
// util.c
extern inline int max_int( int, int );
Wenn Sie dies tun, dann:

    Sie müssen
  • nicht eine Funktion extern inline irgendwo deklarieren.
  • Wenn der Compiler eine Funktion jedoch nicht einbettet, generiert er eine Definition in
  • jeder .c-Datei, in die er eingebunden ist, was wiederum zu einer Aufblähung des Codes führt.
  • Wenn die Funktion statische lokale Variablen hat, wird jede Definition
  • eindeutige Kopien haben (das kann sein, was Sie wollen oder auch nicht).
Abschluss

Inline-Funktionen können bei sinnvoller Verwendung zu Leistungssteigerungen führen. Im Allgemeinen sind nur

sehr kleine Funktionen gute Kandidaten für Inlining.

Ab C 11 können Inline-Funktionen alternativ als constexpr deklariert werden, aber das ist eine Geschichte für ein anderes Mal.

Referenzen

    Linux-Kernel-Codierungsstil, §15 Die Inline-Krankheit.
  • Mythos und Realität über Inline in C99.
  • The Annotated C Reference Manual, Margaret A. Ellis & Bjarne Stroustrup, Addison-Wesley, 1990, ISBN 0-201-51459-1, §7.1.2 Funktionsspezifizierer, S. 99–105.
Freigabeerklärung Dieser Artikel ist reproduziert unter: https://dev.to/pauljlucas/inline-functions-in-c-and-2-2040 Wenn es zu Verletzungen besteht, wenden Sie sich bitte an [email protected], um ihn zu löschen.
Neuestes Tutorial Mehr>

Haftungsausschluss: Alle bereitgestellten Ressourcen stammen teilweise aus dem Internet. Wenn eine Verletzung Ihres Urheberrechts oder anderer Rechte und Interessen vorliegt, erläutern Sie bitte die detaillierten Gründe und legen Sie einen Nachweis des Urheberrechts oder Ihrer Rechte und Interessen vor und senden Sie ihn dann an die E-Mail-Adresse: [email protected] Wir werden die Angelegenheit so schnell wie möglich für Sie erledigen.

Copyright© 2022 湘ICP备2022001581号-3