IMO machen beide die Funktion, nur einen Bereich der Übersetzungseinheit zu haben.
Was ist der Unterschied zwischen “statischer” und “statischer Inline”-Funktion?
Weshalb sollte inline
in eine Header-Datei eingefügt werden, nicht in .c
Datei?
neu_perl
IMO machen beide die Funktion, nur einen Bereich der Übersetzungseinheit zu haben.
Was ist der Unterschied zwischen “statischer” und “statischer Inline”-Funktion?
Weshalb sollte inline
in eine Header-Datei eingefügt werden, nicht in .c
Datei?
Christoph
Standardmäßig ist eine Inline-Definition nur in der aktuellen Übersetzungseinheit gültig.
Wenn die Speicherklasse ist extern
der Bezeichner hat eine externe Verknüpfung und die Inline-Definition stellt auch die externe Definition bereit.
Wenn die Speicherklasse ist static
der Bezeichner hat eine interne Verknüpfung und die Inline-Definition ist in anderen Übersetzungseinheiten unsichtbar.
Wenn die Speicherklasse nicht angegeben ist, ist die Inline-Definition nur in der aktuellen Übersetzungseinheit sichtbar, aber der Bezeichner hat immer noch eine externe Verknüpfung und eine externe Definition muss in einer anderen Übersetzungseinheit bereitgestellt werden. Dem Compiler steht es frei, entweder die Inline- oder die External-Definition zu verwenden, wenn die Funktion innerhalb der aktuellen Übersetzungseinheit aufgerufen wird.
Da es dem Compiler freisteht, jede Funktion einzufügen (und nicht einzufügen), deren Definition in der aktuellen Übersetzungseinheit sichtbar ist (und dank Linkzeitoptimierungen sogar in verschiedenen Übersetzungseinheiten, obwohl der C-Standard dies nicht wirklich berücksichtigt). that), für die meisten praktischen Zwecke gibt es keinen Unterschied zwischen static
und static inline
Funktionsdefinitionen.
Das inline
Spezifizierer (wie die register
storage class) ist nur ein Compiler-Hinweis, und der Compiler kann ihn vollständig ignorieren. Standardkonforme, nicht optimierende Compiler müssen nur ihre Nebeneffekte berücksichtigen, und optimierende Compiler führen diese Optimierungen mit oder ohne explizite Hinweise durch.
inline
und register
sind jedoch nicht nutzlos, da sie den Compiler anweisen, Fehler zu werfen, wenn der Programmierer Code schreibt, der die Optimierungen unmöglich machen würde: Eine externe inline
Die Definition kann nicht auf Bezeichner mit interner Verknüpfung verweisen (da diese in einer anderen Übersetzungseinheit nicht verfügbar wären) oder modifizierbare lokale Variablen mit statischer Speicherdauer definieren (da diese den Status nicht über Übersetzungseinheiten hinweg teilen würden), und Sie können keine Adressen übernehmen von register
-qualifizierte Variablen.
Ich persönlich verwende die Konvention zum Markieren static
Funktionsdefinitionen auch innerhalb von Headern inline
da der Hauptgrund für das Einfügen von Funktionsdefinitionen in Header-Dateien darin besteht, sie inlinierbar zu machen.
Im Allgemeinen verwende ich nur static inline
Funktion u static const
Objektdefinitionen zusätzlich zu extern
Deklarationen innerhalb von Headern.
Ich habe noch nie eine geschrieben inline
Funktion mit einer anderen Speicherklasse als static
.
positiv gestimmt für “Verwenden Sie die Konvention, um statische Funktionsdefinitionen in Headern inline zu markieren”.
– John Z.Li
21. Oktober 2019 um 9:41 Uhr
Ich habe Ihre gesamte Antwort gelesen und verstehe immer noch nicht den semantischen Unterschied zwischen static
und static inline
. Beide machen die Definition für andere Übersetzungseinheiten unsichtbar. Was wäre also ein vernünftiger Grund zu schreiben static inline
Anstatt von static
?
– Benutzer541686
4. August 2020 um 23:20 Uhr
+1 für die äußerst aufschlussreiche Erinnerung, dass sie nicht nutzlos sind, da sie den Compiler anweisen, die Unmöglichkeit, diese Optimierungen durchzuführen, als Fehler zu behandeln!
– mtraceur
25. September 2020 um 20:56 Uhr
@ user541686 Der größte und wichtigste semantische Unterschied ist der static inline
drückt Ihre Absicht/Zustimmung aus, dass es inliniert werden soll, während static
nicht. Um die Definitionen klarzustellen, ist “Semantik” im Grunde ein schickes Wort für “Bedeutung”, und das ist genau dort der wesentlichste semantische Unterschied. Denn beim Quellcode geht es in erster Linie darum, zu beschreiben, was Sie mit dem Code beabsichtigen. Und wenn Sie proaktiv beabsichtigen, Inlining durchzuführen, sollten Sie dies sagen, und inline
ist die “einheimischste” Art, dies in der Sprache von C auszudrücken.
– mtraceur
25. September 2020 um 21:05 Uhr
Clang llvm verwendet einen anderen Schwellenwert für inline angegebene Funktionen: godbolt.org/z/rar9adfbv Ich wage zu sagen, Clang Trunk ist ein “moderner Compiler”
– Etienne M
11. Dezember 2021 um 23:14 Uhr
wenigadv
inline
weist den Compiler an versuchen zu Betten Sie den Funktionsinhalt in den aufrufenden Code ein, anstatt einen tatsächlichen Aufruf auszuführen.
Bei kleinen Funktionen, die häufig aufgerufen werden, kann dies einen großen Leistungsunterschied bewirken.
Dies ist jedoch nur ein “Hinweis”, und der Compiler kann es ignorieren, und die meisten Compiler werden versuchen, “inline” zu setzen, selbst wenn das Schlüsselwort nicht verwendet wird, als Teil der Optimierungen, wo es möglich ist.
zum Beispiel:
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 kleiner als der Code, den der Compiler zum Ausführen des Aufrufs einfügen muss. inline
weist den Compiler im Wesentlichen an, den obigen Code in ein Äquivalent zu konvertieren:
int i;
....
for (i=0; i<999999; i = i+1) { /* do something here */};
Überspringen des eigentlichen Funktionsaufrufs und Rückkehr
Offensichtlich ist dies ein Beispiel, um den Punkt zu verdeutlichen, kein echter Code.
static
bezieht sich auf den Geltungsbereich. In C bedeutet dies, dass die Funktion/Variable nur innerhalb derselben Übersetzungseinheit verwendet werden kann.
Nein, static
bezieht sich auf den Geltungsbereich. In C bedeutet dies, dass die Funktion/Variable nur innerhalb derselben Übersetzungseinheit verwendet werden kann.
– wenigadv
14. Oktober 2011 um 4:00 Uhr
Es ist auch wichtig zu beachten, dass als Inline deklarierter Code in den Header gehört, wo normaler (nicht-Vorlagen-) Quellcode nicht in Header gehen kann, ohne mehrere Neudefinitionsfehler zu verursachen. Selbst wenn also etwas inline deklariert wird, selbst wenn der Compiler sich dafür entscheidet, es nicht zu inlinen, gibt es immer noch ein standardmäßig vorgeschriebenes Verhalten zur Vermeidung mehrfacher Neudefinitionen, das einsetzt.
– VoidStar
14. Oktober 2011 um 4:08 Uhr
@VoidStar Eigentlich static
(mit oder ohne inline
) kann durchaus im Header stehen, sehe keinen Grund warum nicht. Templates ist für C++, diese Frage bezieht sich auf C.
– wenigadv
14. Oktober 2011 um 5:46 Uhr
@littleadv: Der Hauptgrund für das Einfügen von Funktionsdefinitionen in Header-Dateien besteht darin, sie inlinierbar zu machen und sie daher explizit zu markieren inline
ist guter Stil, imo
– Christoph
14. Oktober 2011 um 12:55 Uhr
Eigentlich inline
nicht anweisen den Compiler, um Inlining-Versuche durchzuführen. Es ermöglicht dem Programmierer lediglich, den Funktionskörper ohne ODR-Verletzung in mehrere Übersetzungseinheiten einzufügen. Ein Nebeneffekt davon ist, dass es dem Compiler ermöglicht wird, wenn es möchten inline die Funktion, um dies tatsächlich zu tun.
– Ruslan
2. Januar 2018 um 19:03 Uhr
Aus meiner Erfahrung mit GCC weiß ich das static
und static inline
unterscheidet sich darin, wie der Compiler Warnungen über nicht verwendete Funktionen ausgibt. Genauer gesagt, wenn Sie erklären static
Funktion und sie wird in der aktuellen Übersetzungseinheit nicht verwendet, dann erzeugt der Compiler eine Warnung über nicht verwendete Funktionen, aber Sie können diese Warnung unterdrücken, indem Sie sie in ändern static inline
.
So neige ich dazu, das zu denken static
sollte in Übersetzungseinheiten verwendet werden und von zusätzlichen Compiler-Prüfungen profitieren, um ungenutzte Funktionen zu finden. Und static inline
sollte in Header-Dateien verwendet werden, um Funktionen bereitzustellen, die (aufgrund des Fehlens einer externen Verknüpfung) ohne Ausgabe von Warnungen eingebettet werden können.
Leider kann ich keine Beweise für diese Logik finden. Selbst aus der GCC-Dokumentation konnte ich das nicht schließen inline
sperrt Warnungen zu unbenutzten Funktionen. Ich würde mich freuen, wenn jemand Links zur Beschreibung davon teilen würde.
Mmm, immer noch warning: unused function 'function' [clang-diagnostic-unused-function]
Für ein static inline
Funktion beim Bauen mitclang-tidy
(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 static
& inline
!
– jaques-sam
29. April 2020 um 12:02 Uhr
@DrumM, aber nur bezog sich auf gcc. Aber du hast Recht, das ist wahrscheinlich die bisher beste Erklärung.
– SO_fix_the_vote_sorting_bug
20. Mai 2021 um 14:43 Uhr
Ein Unterschied liegt nicht auf der Sprachebene, sondern auf der beliebten Implementierungsebene: Bestimmte Versionen von gcc entfernen unreferenzierte Dateien static inline
funktioniert standardmäßig von der Ausgabe, bleibt aber einfach static
funktioniert auch ohne Referenz. Ich bin mir nicht sicher, auf welche Versionen dies zutrifft, aber aus praktischer Sicht bedeutet es, dass es eine gute Idee sein könnte, es immer zu verwenden inline
zum static
Funktionen in Kopfzeilen.
gut
In C, static
bedeutet, dass die Funktion oder Variable, die Sie definieren, nur in dieser Datei verwendet werden kann (dh die Kompiliereinheit)
So, static inline
bedeutet die Inline-Funktion, die nur in dieser Datei verwendet werden kann.
BEARBEITEN:
Die Kompiliereinheit sollte sein Die Übersetzungseinheit
Oder in ausgefallenen Worten: es hat eine interne Verknüpfung.
– K-ballo
14. Oktober 2011 um 3:34 Uhr
@AlokSave: Gibt es einen Unterschied zwischen Kompilationseinheit und Übersetzungseinheit? Wenn ja, was ist im Kontext der Sprache C++ besser geeignet?
– legends2k
11. Oktober 2013 um 0:57 Uhr
Ich glaube the compile unit
ist etwas, das ich irrtümlich geschrieben habe, so etwas gibt es nicht, die eigentliche Terminologie ist translation unit
– shengy
11. Oktober 2013 um 0:59 Uhr
Ihre Antwort ist nicht vollständig, da sie hauptsächlich in Header-Dateien über Übersetzungseinheiten hinweg verwendet wird.
– jaques-sam
29. April 2020 um 12:05 Uhr
Matthijs Kooijman
In C++, ein wichtiger Effekt von inline
(das wird meiner Meinung nach in den anderen Antworten noch nicht erwähnt) ist, dass es Linkerfehler verhindert, wenn mehrere Definitionen der Funktion gefunden werden.
Stellen Sie sich eine Funktion vor, die in einer Headerdatei definiert ist, damit sie in die Quelldateien eingebettet werden kann, die den Header enthalten. Wenn der Compiler sich dafür entscheidet nicht Inline (alle Aufrufe zu) dieser Funktion wird die Funktionsdefinition in jede Objektdatei aufgenommen, die darauf verweist (dh nicht alle Aufrufe inline).
Dies kann dazu führen, dass mehrere Definitionen der Funktionen den Linker lesen (jedoch nicht immer, da dies von den Inlining-Entscheidungen des Compilers abhängt). Ohne das inline
Schlüsselwort, erzeugt dies einen Linker-Fehler, aber das inline
Schlüsselwort weist den Linker an, nur eine Definition auszuwählen und den Rest zu verwerfen (von denen erwartet wird, dass sie gleich sind, aber dies wird nicht überprüft).
Das static
Das Schlüsselwort hingegen stellt dies sicher wenn eine Funktion in der Objektdatei enthalten ist, ist sie für diese Objektdatei privat. Wenn mehrere Objektdateien dieselbe Funktion enthalten, existieren sie nebeneinander und alle Aufrufe der Funktion verwenden ihre “eigene” Version. Das bedeutet, dass mehr Speicher belegt wird. In der Praxis bedeutet dies meiner Meinung nach, dass mit static
für Funktionen, die in Header-Dateien definiert sind, ist keine gute Idee, besser einfach zu verwenden inline
.
In der Praxis bedeutet dies auch das static
Funktionen können keine Linker-Fehler erzeugen, daher ist der Effekt von inline
oben ist nicht wirklich nützlich für static
Funktionen. Wie jedoch von one in einer anderen Antwort vorgeschlagen, Hinzufügen inline
kann hilfreich sein, um Warnungen für ungenutzte Funktionen zu vermeiden.
Beachten Sie, dass das obige für C++ gilt. In C, inline
funktioniert etwas andersund Sie müssen explizit eine angeben extern
-Deklaration in einer einzelnen Quelldatei, um die Inline-Funktion in diese Objektdatei emittieren zu lassen, damit sie für alle nicht eingebetteten Verwendungen verfügbar ist. Mit anderen Worten, inline
bedeutet, dass eine Funktion in keine Quelldatei ausgegeben wird, auch wenn nicht alle Aufrufe eingebettet sind, es sei denn, es ist auch als angegeben extern
und dann es ist ausgegeben (selbst wenn alle Ortsgespräche eingebettet sind). Ich bin mir nicht sicher, wie das zusammenwirkt static
obwohl.
Oder in ausgefallenen Worten: es hat eine interne Verknüpfung.
– K-ballo
14. Oktober 2011 um 3:34 Uhr
@AlokSave: Gibt es einen Unterschied zwischen Kompilationseinheit und Übersetzungseinheit? Wenn ja, was ist im Kontext der Sprache C++ besser geeignet?
– legends2k
11. Oktober 2013 um 0:57 Uhr
Ich glaube the compile unit
ist etwas, das ich irrtümlich geschrieben habe, so etwas gibt es nicht, die eigentliche Terminologie ist translation unit
– shengy
11. Oktober 2013 um 0:59 Uhr
Ihre Antwort ist nicht vollständig, da sie hauptsächlich in Header-Dateien über Übersetzungseinheiten hinweg verwendet wird.
– jaques-sam
29. April 2020 um 12:05 Uhr
Prometheus
Ein in der Reihe Definition nicht externly verknüpft.
// average.h
#ifndef AVERAGE_H
#define AVERAGE_H
inline double average(double a, double b);
#endif
Versuch, anzurufen in der Reihe Funktion mit der obigen Definition aus einem anderen Modul nach es wurde vorverarbeitet oder mit einer ac-Datei verknüpft, führt zu einem Fehler.
Es gibt zwei Möglichkeiten, dieses Problem zu lösen:
// average.h
#ifndef AVERAGE_H
#define AVERAGE_H
static inline double average(double a, double b);
#endif
#include "average.h"
extern double average(double a ,double b){
return (a + b) / 2;
}
Verwandte Frage: Statisch vs. Inline für Funktionen, die in Header-Dateien implementiert sind
– m7913d
9. März um 16:37 Uhr