Ist das Schlüsselwort extern für die Funktion in C überhaupt notwendig?

Lesezeit: 6 Minuten

Es scheint mir, dass selbst wenn ich auf eine Funktion in einer anderen Datei ohne externe Deklaration verweise, gcc diese Einheit immer noch kompilieren kann. Ich frage mich also, ob die Extern-Deklaration irgendwo für die Funktion notwendig ist? Ich weiß, dass Sie extern für Variablen benötigen.

  • mögliches Duplikat von Effekte des Schlüsselworts extern auf C-Funktionen

    – Ciro Santilli OurBigBook.com

    19. Mai 2015 um 7:36 Uhr

Benutzeravatar von Prasoon Saurav
Prasun Saurav

Funktionen haben standardmäßig einen externen Speicherklassenbezeichner (es sei denn, sie sind explizit als statisch definiert)

extern Speicherklassenspezifizierer

Wenn die Deklaration eine Funktion beschreibt oder außerhalb einer Funktion erscheint und ein Objekt mit externer Verknüpfung beschreibt, das Schlüsselwort extern ist optional. Wenn Sie keinen Speicherklassenbezeichner angeben, wird davon ausgegangen, dass die Funktion über eine externe Verknüpfung verfügt.

….

Aufgrund der inkompatiblen Deklarationen ist es ein Fehler, eine Deklaration für dieselbe Funktion mit dem Speicherklassenbezeichner static vor der Deklaration ohne Speicherklassenbezeichner einzufügen. Das Einschließen des externen Speicherklassenbezeichners in die ursprüngliche Deklaration ist gültig und die Funktion hat eine interne Verknüpfung.

Es ist nicht notwendig, aber ich bevorzuge es in Kopfzeilen, um die Idee zu verstärken, dass diese Funktion woanders definiert ist.

Für mich das:

int func(int i);

ist eine Vorwärtsdeklaration einer Funktion, die später benötigt wird, während dies:

extern int func(int i);

ist eine Deklaration einer Funktion, die hier verwendet, aber an anderer Stelle definiert wird.

Die beiden Leitungen sind funktional identisch, aber ich verwende die extern Schlüsselwort, um den Unterschied zu dokumentieren, und für die Konsistenz mit regulären Variablen (wobei der Unterschied ist wichtig und hat genau diese Bedeutung).

  • Ich muss sagen, ich finde es in Kopfzeilen extrem hässlich, weil es dazu führt, dass Prototypen mit ziemlicher Sicherheit länger als 80 Zeichen werden, was zu unterbrochenen Zeilen oder horizontalem Scrollen führt, was beides nicht angenehm ist.

    – R.. GitHub HÖR AUF, EIS ZU HELFEN

    10. März 2011 um 4:48 Uhr

  • @R.. – Diskutabel. Es nimmt nur sieben Zeichen (einschließlich Leerzeichen) ein, was ziemlich wenig ist – es würde Ihnen nur Platz für ein Extra geben const oder höchstens ein Parameter. Es hängt auch davon ab, wie viele Parameter Sie als “zu viele” betrachten.

    – Chris Lutz

    10. März 2011 um 4:53 Uhr

  • Wir können also auch die Behauptungen aufstellen: “Extern ist aus Gründen der Abwärtsbequemlichkeit da (bedeutet nicht Kompatibilität) ?

    – Shamim Hafiz – MSFT

    10. März 2011 um 4:54 Uhr

  • Danke für die Antwort. Aber eine andere Frage ist, dass selbst wenn ich die Deklaration vollständig weggelassen hätte (einschließlich des Schlüsselworts extern und des Funktionsprototyps), sie dennoch kompiliert werden könnte.

    – Xiaolong Li

    10. März 2011 um 5:00 Uhr

  • @Xiaolong Li – Nicht richtig, wenn die Typen etwas anderes als wären ints, und nicht in C99.

    – Chris Lutz

    10. März 2011 um 5:02 Uhr

Sie machen nicht Notwendig “brauchenextern für Variablen.

Als C erfunden wurde, wurden auch Unix-Linker geschrieben, und sie brachten die Kunst auf unangekündigte, aber clevere Weise voran. Ein Beitrag war die Definition aller Symbole als kleine “gemeinsame Blöcke”. Dies ermöglichte eine einzige Syntax für Deklarationen ohne erforderliche Angabe, welches Modul den Speicherplatz zuweist. (Nur ein Modul konnte das Objekt tatsächlich initialisieren, aber niemand musste dies tun.)

Es gibt eigentlich drei Überlegungen.

  1. Forward-Deklarationen für Prototypen. (Optional, da Legacy-C ohne sie kompilieren muss.)

  2. Externe Deklarationen für Nichtfunktionsobjekte (Variablen) in allen Dateien außer einer. (Wird nur auf Nicht-Unix-Systemen benötigt, die auch miese Linker haben. Hoffentlich ist das heutzutage selten.)

  3. Bei Funktionen ist extern bereits die Annahme, wenn kein Funktionsrumpf vorhanden ist, um eine Definition zu bilden.

  • Die Linker auf Mainframes waren weit fortgeschritten gegenüber dem kleinen Unix-ld. Das Konzept von “gemeinsam” war in FORTRAN.

    – Jim Balter

    10. März 2011 um 7:49 Uhr

  • Ich stimme Fortran zu, und einige Linker hatten viele Funktionen. Aber Sie wollten sie nicht wie umfangreiche Hierarchien der Overlay-Unterstützung verwenden. Auf einem dieser “fortgeschrittenen” Mainframe-Linker gab es ein Limit von 500 gemeinsamen Blöcken, aber ld(1) könnte man für jedes Symbol tun.

    – DigitalRoss

    10. März 2011 um 17:14 Uhr

  • Einige Leute wollten sie verwenden, weshalb sie dort waren – aber Overlays waren nicht das, was ich im Sinn hatte, als ich sagte, dass diese Linker fortschrittlich waren. Und die Erhöhung einer Grenze ist kein Fortschritt der Kunst auf unangekündigte, aber clevere Weise.

    – Jim Balter

    10. März 2011 um 23:31 Uhr

  • Ok, aber es war die Behandlung von Symbolen, die die Art von undefinierten Werten ungleich Null hatten, als gemeinsame Blöcke der Größe des Werts, die es ermöglichte, die Grenze zu erhöhen. Diese eine einfache Sache bedeutete, dass Symbole nur wenige Typbits und einen einzigen Wert benötigten, aber Deklarationen zusammenführen, zwischen Daten und BSS entscheiden, Daten und BSS zusammenführen, lokale und globale Versionen von all diesen handhaben und mehrere Definitionen erkennen konnten. Wie wäre es, wenn Sie dasselbe Format für Ein- und Ausgabe verwenden? Und wenn diese Mainframe-Betriebssysteme und Linker etwas Gutes waren, warum sind sie dann so tief vergraben und so vergessen?

    – DigitalRoss

    11. März 2011 um 1:01 Uhr

  • Warum ist BetaMax so tief begraben und jetzt so vergessen? Und ich habe nichts über Betriebssysteme gesagt, aber es gibt eine Menge Gutes, das man über Multics und das Burroughs-Betriebssystem (in Algol geschrieben) sagen könnte, aber solche Dinge gehen Ideologen verloren.

    – Jim Balter

    11. März 2011 um 22:41 Uhr


Soweit ich mich an den Standard erinnere, Alle Funktionsdeklarationen werden standardmäßig als “extern” betrachtet, es muss also nicht explizit angegeben werden. Das macht dieses Schlüsselwort nicht nutzlos, da es auch mit Variablen verwendet werden kann (und wenn das der Fall ist – es ist die einzige Lösung, um Verknüpfungsprobleme zu lösen). Aber mit den Funktionen – ja, es ist optional.

Eine etwas ausführlichere Antwort ist, dass Sie damit Variablen verwenden können, die in einer anderen Quellcodedatei kompiliert wurden, aber keinen Speicher für die Variable reservieren. Um also extern zu verwenden, müssen Sie eine Quellcodedatei oder eine Bibliothekseinheit haben, die Speicherplatz für die Variable auf der obersten Ebene enthält (nicht innerhalb von Funktionen). Jetzt können Sie auf diese Variable verweisen, indem Sie eine externe Variable mit demselben Namen in Ihren anderen Quellcodedateien definieren.

Im Allgemeinen sollte die Verwendung einer externen Definition vermieden werden. Sie führen leicht zu unüberschaubarem Code und Fehlern, die schwer zu lokalisieren sind. Natürlich gibt es Beispiele, bei denen andere Lösungen unpraktisch wären, aber sie sind selten. Beispielsweise sind stdin und stdout Makros, die einer externen Array-Variablen vom Typ FILE* in stdin.h zugeordnet sind; Der Speicherplatz für dieses Array befindet sich in einer standardmäßigen C-Bibliothekseinheit.

1437420cookie-checkIst das Schlüsselwort extern für die Funktion in C überhaupt notwendig?

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

Privacy policy