6.7.4 Funktionsspezifizierer
Eine neue Funktion von C99: Das inline
aus C ++ adaptierte Schlüsselwort ist ein Funktionsspezifizierer , der nur in Funktionsdeklarationen verwendet werden kann. Dies ist nützlich für Programmoptimierungen, bei denen die Definition einer Funktion am Ort eines Aufrufs sichtbar sein muss. (Beachten Sie, dass der Standard nicht versucht, die Art dieser Optimierungen anzugeben.)
Die Sichtbarkeit ist gewährleistet, wenn die Funktion über eine interne Verknüpfung verfügt oder wenn sie über eine externe Verknüpfung verfügt und sich der Aufruf in derselben Übersetzungseinheit wie die externe Definition befindet. In diesen Fällen hat das Vorhandensein des
inline
Schlüsselworts in einer Deklaration oder Definition der Funktion keine Auswirkung, außer dass eine Präferenz angegeben wird, dass Aufrufe dieser Funktion gegenüber Aufrufen anderer Funktionen, die ohne die deklariert wurden, bevorzugt optimiert werden sollteninline
Schlüsselwort .
Die Sichtbarkeit ist ein Problem für einen Aufruf einer Funktion mit externer Verknüpfung, bei der sich der Aufruf in einer anderen Übersetzungseinheit als der Funktionsdefinition befindet. In diesem Fall ist dieinline
ermöglicht Schlüsselwort, dass die Übersetzungseinheit, die den Aufruf enthält, auch eine lokale oder Inline-Definition der Funktion enthält.
Ein Programm kann eine Übersetzungseinheit mit einer externen Definition, eine Übersetzungseinheit mit einer Inline-Definition und eine Übersetzungseinheit mit einer Deklaration, jedoch ohne Definition für eine Funktion enthalten. Anrufe in der letzteren Übersetzungseinheit verwenden wie gewohnt die externe Definition.
Eine Inline-Definition einer Funktion wird als eine andere Definition als die externe Definition angesehen. Wenn ein Aufruf einer Funktion func
mit externer Verknüpfung erfolgt, bei der eine Inline-Definition sichtbar ist, ist das Verhalten dasselbe, als würde beispielsweise eine andere Funktion aufgerufen
__func
mit interner Verknüpfung, erfolgt wäre. Ein konformes Programm darf nicht davon abhängen, welche Funktion aufgerufen wird. Dies ist das Inline-Modell im Standard.
Ein konformes Programm darf sich weder auf die Implementierung unter Verwendung der Inline-Definition noch auf die Implementierung unter Verwendung der externen Definition verlassen. Die Adresse einer Funktion ist immer die Adresse, die der externen Definition entspricht. Wenn diese Adresse jedoch zum Aufrufen der Funktion verwendet wird, kann die Inline-Definition verwendet werden. Daher verhält sich das folgende Beispiel möglicherweise nicht wie erwartet.
inline const char *saddr(void)
{
static const char name[] = "saddr";
return name;
}
int compare_name(void)
{
return saddr() == saddr(); // unspecified behavior
}
Da die Implementierung möglicherweise die Inline-Definition für einen der Aufrufe saddr
und die externe Definition für den anderen verwendet, kann nicht garantiert werden, dass die Gleichheitsoperation 1 (true) ergibt. Dies zeigt, dass sich statische Objekte, die in der Inline-Definition definiert sind, von ihrem entsprechenden Objekt in der externen Definition unterscheiden. Dies motivierte die Einschränkung, nicht einmal ein Nicht- zu definierenconst
dieses Typs zu definieren.
Inlining wurde dem Standard so hinzugefügt, dass es mit der vorhandenen Linker-Technologie implementiert werden kann und eine Teilmenge von C99-Inlining mit C ++ kompatibel ist. Dies wurde erreicht, indem genau eine Übersetzungseinheit, die die Definition einer Inline-Funktion enthält, als diejenige angegeben werden muss, die die externe Definition für die Funktion bereitstellt. Da diese Spezifikation besteht einfach aus einer Erklärung , dass entweder das fehlt inline
Schlüsselwort oder enthält beide inline
und extern
es wird auch durch einen C ++ Übersetzer akzeptiert werden.
Durch Inlining in C99 wird die C ++ - Spezifikation auf zwei Arten erweitert. Wenn eine Funktion inline
in einer Übersetzungseinheit deklariert ist
, muss sie nicht inline
in jeder anderen Übersetzungseinheit deklariert werden. Dies ermöglicht beispielsweise eine Bibliotheksfunktion, die innerhalb der Bibliothek eingebunden werden soll, aber nur über eine externe Definition an anderer Stelle verfügbar ist. Die Alternative, eine Wrapper-Funktion für die externe Funktion zu verwenden, erfordert einen zusätzlichen Namen. Dies kann sich auch nachteilig auf die Leistung auswirken, wenn ein Übersetzer keine Inline-Substitution durchführt.
Zweitens wird die Anforderung, dass alle Definitionen einer Inline-Funktion „genau gleich“ sein müssen, durch die Anforderung ersetzt, dass das Verhalten des Programms nicht davon abhängen sollte, ob ein Aufruf mit einer sichtbaren Inline-Definition oder der externen Definition von a implementiert wird Funktion. Auf diese Weise kann eine Inline-Definition auf ihre Verwendung innerhalb einer bestimmten Übersetzungseinheit spezialisiert werden. Beispielsweise kann die externe Definition einer Bibliotheksfunktion eine Argumentvalidierung enthalten, die für Aufrufe anderer Funktionen in derselben Bibliothek nicht erforderlich ist. Diese Erweiterungen bieten einige Vorteile. Programmierer, die sich Sorgen um die Kompatibilität machen, können sich einfach an die strengeren C ++ - Regeln halten.
Beachten Sie, dass es für Implementierungen nicht geeignet ist, Inline-Definitionen von Standardbibliotheksfunktionen in den Standardheadern bereitzustellen, da dies einen Legacy-Code beschädigen kann, der Standardbibliotheksfunktionen nach dem Einschließen ihrer Header neu deklariert. Das inline
Schlüsselwort soll Benutzern nur eine tragbare Möglichkeit bieten, das Inlining von Funktionen vorzuschlagen. Da die Standardheader nicht portierbar sein müssen, bieten Implementierungen andere Optionen wie:
#define abs(x) __builtin_abs(x)
oder andere nicht tragbare Mechanismen zum Inlinen von Standardbibliotheksfunktionen.