Was ist der Unterschied zwischen “statischer” und “statischer Inline”-Funktion?

Lesezeit: 10 Minuten

Benutzeravatar von new_perl
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?

  • Verwandte Frage: Statisch vs. Inline für Funktionen, die in Header-Dateien implementiert sind

    – m7913d

    9. März um 16:37 Uhr


Benutzeravatar von Christoph
Christoph

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

Wenn die Speicherklasse ist externder Bezeichner hat eine externe Verknüpfung und die Inline-Definition stellt auch die externe Definition bereit.

Wenn die Speicherklasse ist staticder 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 inlineda 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

Benutzeravatar von littleadv
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.

Benutzeravatar von shengy
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

Benutzeravatar von Matthijs Kooijman
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 externund dann es ist ausgegeben (selbst wenn alle Ortsgespräche eingebettet sind). Ich bin mir nicht sicher, wie das zusammenwirkt staticobwohl.

  • 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

Benutzeravatar von Prometheus
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:

  1. mach es a statisch inline Funktionsdefinition. Beispiel:
// average.h
#ifndef AVERAGE_H
#define AVERAGE_H
static inline double average(double a, double b);
#endif
  1. Fügen Sie die Definition aus der c-Datei hinzu und erstellen Sie sie extern. Beispiel:
#include "average.h"
extern double average(double a ,double b){ 
  return (a + b) / 2;
}

1424530cookie-checkWas ist der Unterschied zwischen “statischer” und “statischer Inline”-Funktion?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy