Static deklarierten Funktionen in "C" - header-Dateien
Für mich ist es eine Regel zu definieren und deklarieren von statischen Funktionen im Quellcode-Dateien, die ich meine .c-Dateien.
Jedoch in sehr seltenen Situationen, ich sah Menschen, die die Deklaration in der header-Datei.
Da statische Funktionen haben, die interne Verlinkung, die wir benötigen, definieren Sie es in jede Datei binden wir die header-Datei, wo die Funktion deklariert ist. Das sieht ziemlich seltsam und weit Weg von dem was wir wollen in der Regel, wenn man erklärt etwas als statisch.
Auf der anderen Seite, wenn jemand naiv versucht, die Funktion zu nutzen, ohne es zu definieren der compiler Beschwerde. Also in einem gewissen Sinn ist nicht wirklich unsicher ist, tun Sie das auch klingen seltsam.
Meine Fragen sind:
- Was ist das problem der Deklaration von statischen Funktionen in header-Dateien?
- Was sind die Risiken?
- Was die Auswirkungen in der Zusammenstellung Zeit?
- Gibt es Risiken in der Laufzeit?
Kleine
static inline
Funktionen werden gelegentlich auch als accessor-Funktionen in die Struktur-Datentypen, die als (besseren) Ersatz für Präprozessor-Makros. Im Gegensatz zu Makros, statische inline-Funktionen bieten compile-Zeit-Typ-Prüfung und können sich auf Ihre Parametern mehrere Male (das ist problematisch, mit Präprozessor-Makros).Guter Punkt. Sehen Sie den source-code kann der compiler besser Optimierungen (inlining wird einer von Ihnen) ohne linker Hilfe.
Kann jemand sagen, was die Größe der Auswirkungen definieren, die die gleiche Funktion immer und immer wieder in vielen compilation-Einheiten ist? Ich nehme an, der linker (davon ausgehend, dass verschiedene TUs) können Falten Sie Sie eine so das den Objekt-code multipliziert wird?
Für makro-Ersatz statische inline-Funktionen minimal. Funktionsaufrufe neigen, müssen einige register mischen (die übergabe der Parameter), in der Erwägung, dass viele Compiler können, vermeiden Sie solche, die für die statische inline-Funktionen (und stattdessen die Arbeit an den Registern, die haben die Daten schon). Es variiert sehr stark, natürlich, aber ich würde sagen, dass, wenn inlining der Funktion erheblich, erhöht die code-Größe, das sollte die Funktion nicht inline in den ersten Platz.
InformationsquelleAutor miguel azevedo | 2017-02-05
Du musst angemeldet sein, um einen Kommentar abzugeben.
Zunächst möchte ich klären, mein Verständnis der situation, die Sie beschreiben: Die Kopfzeile enthält (nur) eine statische Funktion Erklärung, während die C-Datei enthält die definition, d.h. die Funktion der source-code. Zum Beispiel
einige.h:
einige.c:
Wenn dies der situation, die Sie beschreiben, ich nehmen Sie Problem mit Ihrer Bemerkung
Wenn Sie die Funktion deklarieren, aber verwenden Sie es nicht in einer übersetzung Einheit, ich glaube nicht, dass Sie haben, es zu definieren. gcc akzeptiert, dass mit einer Warnung; der standard scheint nicht zu verbieten, es sei denn, ich habe etwas verpasst. Das kann wichtig sein, in deinem Szenario, weil übersetzungseinheiten, die nicht der Funktion, sondern den Kopf mit seiner Erklärung nicht haben, um eine nicht verwendete definition.
Nun betrachten wir die Fragen:
Was ist das problem der Deklaration von statischen Funktionen in header-Dateien?
Es ist etwas ungewöhnlich. Würde es Sinn machen, nur wenn die meisten übersetzungseinheiten, die den Kopf mit einer bestimmten Funktion Erklärung verwenden in der Tat, die Funktion, weil die Haupt-Gründe und nutzen von statischen Funktionen, ist Ihre eingeschränkte Sicht. Sie verschmutzen nicht die Umwelt den globalen Namensraum (des nur ein C hat) und kann verwendet werden, als ein armer Mann ist "private" Methoden, die nicht verwendet werden sollen die Allgemeine öffentlichkeit und damit erklärt, dass Sie nur zugänglich, wo Sie benötigt werden.
Auf der anderen Seite kann es sogar nützlich sein, um eine Deklaration in einem header, da es sicherstellt, dass alle lokalen Definitionen Stimmen zumindest in der Funktionssignatur. (Zwei Funktionen mit dem gleichen Namen, aber unterschiedlichen Rückgabetypen Ursache wäre ein compile-Zeit Fehler, die in C (und C++); verschiedene parameter-Typen führen zu einer compile-Zeit-Fehler nur in C, weil es nicht überladen von Funktionen.) Von dieser Einheitlichkeit der Perspektive es kann ausreichend sein, um die Funktion richtige definition in der header-Datei sofort, wenn die Funktion gemeint ist, identisch in jeder übersetzungseinheit. Der Aufwand dieses Ansatzes hängt davon ab, ob alle übersetzungseinheiten, die den Kopf auch wirklich die Funktion nutzen.
Was sind die Risiken?
Ich nicht sehen Risiken in Ihrem Szenario. (Im Gegensatz zu der auch die Funktion definition in einem der Kopfzeile kann gegen das Prinzip der Kapselung.)
, Was die Auswirkungen in der Zusammenstellung Zeit?
Eine Funktionsdeklaration ist klein und die Komplexität gering ist, so ist der Aufwand mit der zusätzlichen Funktion-Deklarationen in einer header ist wahrscheinlich vernachlässigbar. Aber wenn Sie erstellen und beinhalten einen zusätzlichen header für die Erklärung der in vielen übersetzungseinheiten die Datei-handling-Aufwand kann erheblich sein (d.h. der compiler idles, eine Menge, während er darauf wartet, dass der header I/O).
Gibt es Risiken in der Laufzeit?
Ich sehe keine.
InformationsquelleAutor Peter A. Schneider
Dies ist nicht eine Antwort auf die genannten Fragen, aber hoffentlich zeigt warum einer Umsetzung könnte ein
static
(oderstatic inline
) - Funktion in einer header-Datei.Kann ich persönlich nur denke zwei gute Gründe, um zu erklären, dass bestimmte Funktionen
static
in einer header-Datei:Wenn die header-Datei komplett implementiert eine Schnittstelle, die sollte nur sichtbar sein in der aktuellen compilation unit
Dies ist extrem selten, aber könnte nützlich sein, z.B. in einem pädagogischen Kontext, an irgendeinem Punkt während der Entwicklung von einigen Beispiel-Bibliothek; oder vielleicht, wenn er eine Schnittstelle zu einer anderen Programmiersprache mit minimalem code.
Entwickler können wählen, dies zu tun, wenn die Bibliothek oder interaface Implementierung ist trivial und fast so, und die Benutzerfreundlichkeit (der Entwickler anhand der header-Datei) ist wichtiger als code-Größe. In diesen Fällen werden die Deklarationen in der header-Datei verwenden oft Präprozessor-Makros, so dass die gleiche header-Datei aufgenommen werden, mehr als einmal, einige Sortieren von grob-Polymorphismus in C.
Hier ist ein Beispiel aus der Praxis: Schießen-selbst-in-den-Fuß-Spielplatz für linear congruential Pseudo-zufälligen Zahl-Generatoren. Denn die Umsetzung einer lokalen compilation-unit, die jede compilation unit wird Ihre eigenen Kopien der PRNG. Dieses Beispiel zeigt auch, wie grob Polymorphismus realisiert werden kann C.
prng32.h:
Ein Beispiel für die Verwendung der oben Beispiel-prng32.h:
Der Grund für die Markierung sowohl der
_state
variable und die_next()
Funktionstatic
ist, dass auf diese Weise jede compilation unit enthält die header-Datei hat Ihre eigene Kopie der Variablen und Funktionen -- hier Ihre eigene Kopie des PRNG. Jeder muss separat ausgesät, natürlich; und wenn der Setzliste auf den gleichen Wert, wird der Ertrag der gleichen Reihenfolge.Generell sollte man sich scheuen, solche Polymorphismus versuche in C, denn es führt zu komplizierten Präprozessor-makro-Spielereien, so dass die Umsetzung sehr viel schwieriger zu verstehen, zu pflegen und zu modifizieren als nötig.
Jedoch, wenn erkunden der parameter Raum von einigen Algorithmus-wie hier die Arten von 32-bit-linear-congruential-Generatoren, dies ermöglicht uns die Nutzung einer einzigen Implementierung für jeden der Generatoren, die wir untersuchen, die Gewährleistung gibt es keine Umsetzung Unterschiede zwischen Ihnen. Beachten Sie, dass auch dieser Fall ist mehr wie ein Entwicklungswerkzeug, und nicht etwas, das Sie sehen sollten, in einer implementation für andere zu verwenden.
Wenn der header implementiert einfache
static inline
- accessor-FunktionenPräprozessor-Makros werden Häufig verwendet, um zu vereinfachen-code den Zugriff auf komplizierte Struktur, Arten.
static inline
Funktionen sind ähnlich, außer, dass Sie bieten auch die Typprüfung zur compile-Zeit, und können sich auf Ihre Parameter, die mehrmals (mit Makros, die problematisch ist).Einem praktischen Anwendungsfall eine einfache Schnittstelle zum Lesen von Dateien mithilfe von low-level POSIX.1 I/O (mit
<unistd.h>
und<fcntl.h>
statt<stdio.h>
). Ich habe dies getan, mich beim Lesen sehr groß (Dutzende von Megabyte zu Gigabyte reichen) text-Dateien mit reellen zahlen (mit einem custom float/double-parser), der GNU C standard I/O ist nicht besonders schnell.Beispielsweise inbuffer.h:
Beachten Sie, dass die oben
inbuffer_skip()
undinbuffer_getc()
nicht überprüfen, wennib
ist nicht NULL; dies ist typisch für solche Funktionen. Diese accessor-Funktionen sind davon ausgegangen, dass "in den schnellen Pfad", also sehr oft. In solchen Fällen, auch der Funktionsaufruf-overhead Angelegenheiten (und ist) vermiedenstatic inline
Funktionen, da Sie dupliziert in den code an der call-site).Trivial-accessor-Funktionen, wie die oben
inbuffer_skip()
undinbuffer_getc()
, kann auch ermöglichen es dem compiler, vermeiden Sie das registrieren von Bewegungen beteiligt-Funktion aufrufen, weil Funktionen erwarten Parameter, um sich in bestimmten Registern oder auf dem stack, in der Erwägung, dass inline-Funktionen angepasst werden können (wrt. registrieren verwenden), um den code rund um die inline-Funktion.Persönlich kann ich empfehlen, schreiben Sie ein paar test-Programme mit Hilfe der nicht-inline-Funktionen ersten, und vergleichen Sie die Leistung und Ergebnisse, um die inline-Versionen. Vergleicht man die Ergebnisse sorgen für die inline-Versionen haben keine bugs (aus von einem Typ ist hier üblich!), und vergleicht man die Leistung und die erzeugten binaries (Größe zumindest) sagt Ihnen, ob inlining ist es Wert, im Allgemeinen.
Der kanonische Weg, um Dankbarkeit auf StackOverflow ist upvote und/oder als Marke der akzeptierten Antworten ;-).
A. Schneider habe ich versucht sieht aber ich habe nicht das Privileg ?
Genau.
Es ist, weil Sie ein neues Mitglied; auf Stack-Überlauf und damit zusammenhängende Websites, erhalten Sie zusätzliche Berechtigungen wie Sie gewinnen Ruf. Zum Beispiel, um upvote ein post, den Sie brauchen, um 15 Ruf oder mehr. Also, Mach dir keine sorgen über upvoting nur noch. Außerdem können Sie immer wieder kommen und upvote Beiträge später auf-Sie können nur upvote jede Antwort einmal, nachdem alle.
InformationsquelleAutor Nominal Animal
Warum würden Sie wollen, eine sowohl Globale als auch statische Funktion? In c, Funktionen global sind standardmäßig. Verwenden Sie nur statische Funktionen, wenn Sie wollen, beschränken Sie den Zugriff auf eine Funktion, um die Datei, in der Sie deklariert sind. So dass Sie aktiv den Zugriff beschränken, indem die Deklaration static...
Die einzige Voraussetzung für die Implementierungen in die header-Datei für c++ template-Funktionen und template-Memberfunktionen.
"global" ist kein exakter Begriff. Manche Leute nennen
static int x;
im Datei-Bereich, eine Globale variable.InformationsquelleAutor JHBonarius