Was ist der Unterschied zwischen der Funktion "statisch" und "statisch inline"?

123

IMO beide machen die Funktion so, dass sie nur einen Bereich der Übersetzungseinheit hat.

Was ist der Unterschied zwischen der Funktion "statisch" und "statisch inline"?

Warum sollte inlinein eine Header-Datei eingefügt werden, nicht in eine .cDatei?

new_perl
quelle

Antworten:

109

inlineWeist den Compiler an, zu versuchen, den Funktionsinhalt in den aufrufenden Code einzubetten, anstatt einen tatsächlichen Aufruf auszuführen.

Für kleine Funktionen, die häufig aufgerufen werden und einen großen Leistungsunterschied bewirken können.

Dies ist jedoch nur ein "Hinweis", und der Compiler ignoriert ihn möglicherweise. Die meisten Compiler versuchen, "inline" zu arbeiten, auch wenn das Schlüsselwort im Rahmen der Optimierungen nicht verwendet wird, sofern dies möglich ist.

beispielsweise:

static int Inc(int i) {return i+1};
.... // some code
int i;
.... // some more code
for (i=0; i<999999; i = Inc(i)) {/*do something here*/};

Diese enge Schleife führt bei jeder Iteration einen Funktionsaufruf aus, und der Funktionsinhalt ist tatsächlich erheblich geringer als der Code, den der Compiler zum Ausführen des Aufrufs eingeben muss. inlinewird den Compiler im Wesentlichen anweisen, den obigen Code in ein Äquivalent von zu konvertieren:

 int i;
 ....
 for (i=0; i<999999; i = i+1) { /* do something here */};

Überspringen des eigentlichen Funktionsaufrufs und Zurückkehren

Offensichtlich ist dies ein Beispiel, um den Punkt zu zeigen, kein wirklicher Code.

staticbezieht sich auf den Umfang. In C bedeutet dies, dass die Funktion / Variable nur innerhalb derselben Übersetzungseinheit verwendet werden kann.

littleadv
quelle
4
Nein, staticbezieht sich auf den Umfang. In C bedeutet dies, dass die Funktion / Variable nur innerhalb derselben Übersetzungseinheit verwendet werden kann.
littleadv
8
Es ist auch wichtig zu beachten, dass als Inline deklarierter Code in den Header gehört, wo normaler Quellcode (ohne Vorlage) nicht in Header eingefügt werden kann, ohne mehrere Neudefinitionsfehler zu verursachen. Selbst wenn etwas inline deklariert wird, selbst wenn der Compiler es nicht inline deklariert, gibt es dennoch eine standardmäßige Mehrfach-Neudefinition, die ein Verhalten vermeidet, das einsetzt.
VoidStar
13
@VoidStar Eigentlich kann static(mit oder ohne inline) perfekt im Header sein, sehe keinen Grund warum nicht. Vorlagen ist für C ++, diese Frage ist über C.
littleadv
2
@littleadv: Der Hauptgrund für das Einfügen von Funktionsdefinitionen in Header-Dateien besteht darin, sie inlinierbar zu machen. Daher inlineist es ein guter Stil, sie explizit zu markieren , imo
Christoph
9
Eigentlich inlinenicht anweisen , die Compiler alle Versuche zu tun , bei inlining. Der Programmierer kann lediglich den Funktionskörper in mehrere Übersetzungseinheiten ohne ODR-Verletzung aufnehmen. Ein Nebeneffekt davon ist, dass es dem Compiler ermöglicht wird, dies tatsächlich zu tun , wenn er die Funktion inline würde .
Ruslan
95

Standardmäßig ist eine Inline-Definition nur in der aktuellen Übersetzungseinheit gültig.

Wenn die Speicherklasse ist extern, hat der Bezeichner eine externe Verknüpfung und die Inline-Definition liefert auch die externe Definition.

Wenn die Speicherklasse ist static, hat der Bezeichner eine interne Verknüpfung und die Inline-Definition ist in anderen Übersetzungseinheiten nicht sichtbar.

Wenn die Speicherklasse nicht angegeben ist, ist die Inline-Definition nur in der aktuellen Übersetzungseinheit sichtbar, der Bezeichner ist jedoch weiterhin extern verknüpft, und eine externe Definition muss in einer anderen Übersetzungseinheit bereitgestellt werden. Dem Compiler steht es frei, entweder die Inline- oder die externe Definition zu verwenden, wenn die Funktion innerhalb der aktuellen Übersetzungseinheit aufgerufen wird.

Da der Compiler frei ist, jede Funktion zu inline (und nicht inline), deren Definition in der aktuellen Übersetzungseinheit sichtbar ist (und dank der Optimierung der Verbindungszeit auch in verschiedenen Übersetzungseinheiten, obwohl der C-Standard dies nicht wirklich berücksichtigt dass) für die meisten praktischen Zwecke gibt es keinen Unterschied zwischen staticund static inlineFunktionsdefinitionen.

Der inlineBezeichner (wie die registerSpeicherklasse) ist nur ein Compiler-Hinweis, und der Compiler kann ihn vollständig ignorieren. Standardkonforme nicht optimierende Compiler müssen nur ihre Nebenwirkungen berücksichtigen, und optimierende Compiler führen diese Optimierungen mit oder ohne explizite Hinweise durch.

inlineund registersind jedoch nicht nutzlos, da sie den Compiler anweisen, Fehler auszulösen, wenn der Programmierer Code schreibt, der die Optimierungen unmöglich macht: Eine externe inlineDefinition kann nicht auf Bezeichner mit interner Verknüpfung verweisen (da diese in einer anderen Übersetzungseinheit nicht verfügbar wären). oder definieren Sie modifizierbare lokale Variablen mit statischer Speicherdauer (da diese den Status für alle Übersetzungseinheiten nicht gemeinsam nutzen), und Sie können keine Adressen von registerqualifizierten Variablen verwenden.

Persönlich verwende ich die Konvention, um staticFunktionsdefinitionen auch in Headern zu markieren inline, da der Hauptgrund für das Einfügen von Funktionsdefinitionen in Header-Dateien darin besteht, sie inlinierbar zu machen.

Im Allgemeinen verwende ich neben Deklarationen in Headern nur static inlineFunktions- und static constObjektdefinitionen extern.

Ich habe noch nie eine inlineFunktion mit einer anderen Speicherklasse als geschrieben static.

Christoph
quelle
8
Dies ist die richtige Antwort. Jede Antwort, über die gesprochen wird, inlineals ob sie tatsächlich auf Inlining zutrifft, ist irreführend und wohl falsch. Kein moderner Compiler verwendet es als Hinweis für Inline oder benötigt es, um das Inlining einer Funktion zu ermöglichen.
Tyg13
1
upvoted für "Verwenden Sie die Konvention, um statische Funktionsdefinitionen in Headern inline zu markieren".
John Z. Li
21

Aus meiner Erfahrung mit GCC weiß ich das staticund static inlineunterscheidet mich darin, wie der Compiler Warnungen vor nicht verwendeten Funktionen ausgibt. Genauer gesagt, wenn Sie deklarierenstatic Funktion und sie in der aktuellen Übersetzungseinheit nicht verwendet wird, erzeugt der Compiler eine Warnung über nicht verwendete Funktionen. Sie können diese Warnung jedoch verhindern, indem Sie sie in ändern static inline.

Daher neige ich dazu, das zu denken static dies in Übersetzungseinheiten verwendet werden sollte und von zusätzlichen Überprüfungs-Compiler-Funktionen profitiert, um nicht verwendete Funktionen zu finden. Und static inlinesollte in Header-Dateien verwendet werden, um Funktionen bereitzustellen, die (aufgrund fehlender externer Verknüpfungen) ohne Warnungen integriert werden können.

Leider kann ich keine Beweise für diese Logik finden. Selbst aus der GCC-Dokumentation konnte ich nicht schließen, dass inlinenicht verwendete Funktionswarnungen verhindert werden. Ich würde mich freuen, wenn jemand Links zur Beschreibung davon teilt.

nur
quelle
Mmm, habe noch warning: unused function 'function' [clang-diagnostic-unused-function]eine static inlineFunktion beim clang-tidyErstellen mit (v8.0.1), die in einer anderen Übersetzungseinheit verwendet wird. Aber definitiv ist dies eine der besten Erklärungen und Gründe für die Kombination von static& inline!
DrumM
6

In C staticbedeutet , dass die von Ihnen definierte Funktion oder Variable nur in dieser Datei verwendet werden kann (dh in der Kompilierungseinheit).

Bedeutet static inlinealso die Inline-Funktion, die nur in dieser Datei verwendet werden kann.

BEARBEITEN:

Die Kompilierungseinheit sollte die Übersetzungseinheit sein

Shengy
quelle
2
Oder in ausgefallenen Worten: Es hat eine interne Verknüpfung.
K-Ballo
@AlokSave: Gibt es einen Unterschied zwischen Kompilierungseinheit und Übersetzungseinheit ? Wenn ja, welche ist im Kontext der C ++ - Sprache besser geeignet?
Legends2k
Ich glaube, es the compile unitist etwas , was ich irrtümlich geschrieben habe, es gibt so etwas nicht, die eigentliche Terminologie isttranslation unit
Shengy
Ihre Antwort ist nicht vollständig, da sie hauptsächlich in Header-Dateien über Übersetzungseinheiten hinweg verwendet wird.
DrumM
5

Ein Unterschied, der nicht auf der Sprachebene, sondern auf der beliebten Implementierungsebene liegt: Bestimmte Versionen von gcc entfernen standardmäßig nicht referenzierte static inlineFunktionen aus der Ausgabe, behalten jedoch einfache staticFunktionen bei, auch wenn sie nicht referenziert sind. Ich bin nicht sicher, für welche Versionen dies gilt, aber aus praktischer Sicht bedeutet dies, dass es eine gute Idee sein kann, immer inlinefür staticFunktionen in Headern zu verwenden.

R .. GitHub HÖREN SIE AUF, EIS ZU HELFEN
quelle
Was ist mit der Verwendung inlinein der Definition? Bedeuten Sie auch, dass Sie es nicht für externFunktionen verwenden?
new_perl
Gilt das immer noch für die aktuelle Version von GCC? Ihre Antwort wäre viel interessanter, wenn Sie ein Beispiel geben und auflisten, welche Version von GCC dies tut.
Z Boson
@Zboson: Ich habe diese Informationen nicht sofort zur Verfügung und habe im Moment keine Zeit, viele gcc-Versionen einzurichten und zu testen, aber ich stimme zu, dass dies nützliche Informationen wären. Sie könnten wahrscheinlich feststellen, wann gcc zum ersten Mal damit begann, nicht verwendete statische Funktionen / Objekte zu optimieren, indem Sie sich den Verlauf attribute((used))und seine Verwendung ansehen, damit asm auf ansonsten nicht referenzierte staticFunktionen und Daten verweisen kann.
R .. GitHub STOP HELPING ICE