So verwenden Sie das Schlüsselwort extern in C richtig

Lesezeit: 8 Minuten

Benutzeravatar von lillq
lillq

Meine Frage ist, wann eine Funktion mit dem referenziert werden sollte extern Schlüsselwort in C.

Ich sehe nicht, wann dies in der Praxis verwendet werden sollte. Während ich ein Programm schreibe, werden alle Funktionen, die ich verwende, durch die Header-Dateien verfügbar gemacht, die ich eingeschlossen habe. Also warum sollte es nützlich sein extern um Zugriff auf etwas zu erhalten, das nicht in der Header-Datei verfügbar gemacht wurde?

Ich könnte darüber nachdenken, wie extern funktioniert falsch, und wenn ja, bitte korrigieren Sie mich.

Auch.. Sollten Sie extern etwas, wenn es sich um die Standarddeklaration ohne das Schlüsselwort in einer Header-Datei handelt?

  • verwandt für Funktionen: stackoverflow.com/questions/856636/… für Variablen: stackoverflow.com/questions/1433204

    – Ciro Santilli OurBigBook.com

    19. Juni 2015 um 2:16 Uhr


Benutzeravatar von bluebrother
blauer Bruder

extern ändert die Verknüpfung. Mit dem Schlüsselwort wird angenommen, dass die Funktion / Variable woanders verfügbar ist, und die Auflösung wird dem Linker übertragen.

Es gibt einen Unterschied zwischen extern auf Funktionen und auf Variablen.

Zum Variablen es instanziiert nicht die Variable selbst, dh reserviert keinen Speicher. Das muss woanders gemacht werden. Daher ist es wichtig, wenn Sie die Variable von woanders importieren möchten.

Zum Funktionen, teilt dies dem Compiler nur mit, dass die Verknüpfung extern ist. Da dies der Standard ist (verwenden Sie das Schlüsselwort static um anzuzeigen, dass eine Funktion nicht durch externe Verknüpfung gebunden ist), müssen Sie sie nicht explizit verwenden.

  • Warum gibt es dann das gleiche externe Ding in Git: eine sehr beliebte und moderne Software, überprüfen Sie es: github.com/git/git/blob/master/strbuf.h

    – rsjethani

    11. August 2013 um 14:11 Uhr

  • K & R bemerkt nicht, dass es standardmäßig ist, die Funktion als “extern” zu deklarieren, aber diese Antwort löst meine Verwirrung!

    – agtyrant

    22. Februar 2014 um 8:12 Uhr

  • @rsjethani Ich denke, es soll das Dokument strenger und formatierter machen.

    – agtyrant

    22. Februar 2014 um 8:21 Uhr

  • Vielleicht eine dumme Frage, aber wie verhält sich das zur Vorwärtsdeklaration?

    – weberc2

    16. November 2015 um 15:13 Uhr

Benutzeravatar von lillq
lillq

extern teilt dem Compiler mit, dass diese Daten irgendwo definiert sind und mit dem Linker verbunden werden.

Mit Hilfe der Antworten hier und im Gespräch mit ein paar Freunden hier ist das praktische Beispiel einer Verwendung extern.

Beispiel 1 – um eine Falle aufzuzeigen:

stdio.h:

int errno;

myCFile1.c:

#include <stdio.h>

// Code using errno...

myCFile2.c:

#include <stdio.h>

// Code using errno...

Wenn myCFile1.o und myCFile2.o verknüpft sind, jede der c-Dateien haben separate Kopien von errno. Dies ist ein Problem wie das gleiche errno soll in allen verlinkten Dateien vorhanden sein.

Beispiel 2 – Die Reparatur.

stdio.h:

extern int errno;

stdio.c:

int errno;

myCFile1.c:

#include <stdio.h>

// Code using errno...

myCFile2.c:

#include <stdio.h>

// Code using errno...

Wenn jetzt beides myCFile1.o und MyCFile2.o vom Linker verlinkt sind, zeigen sie beide auf dasselbe errno. So löst sich die Implementierung mit extern.

  • Das Problem ist nicht, dass die Module myCFile1 und myCFile2 eine separate Kopie von errno haben, sondern dass sie beide ein Symbol namens “errno” anzeigen. Wenn der Linker dies sieht, weiß er nicht, welche “errno” er auswählen soll, also springt er mit einer Fehlermeldung ab.

    – zack

    2. Februar 2009 um 16:52 Uhr

  • was bedeutet eigentlich “linked by the linker”? jeder benutzt diesen Begriff, ich finde keine Definition 🙁

    – Marcel Falliere

    1. Oktober 2013 um 6:59 Uhr

  • @MarcelFalliere Wiki ~ Der Compiler kompiliert jede Quelldatei eigenständig und erstellt eine Objektdatei für jede Quelldatei. Linker verknüpft diese Objektdateien mit 1 ausführbaren Datei.

    – Bitter blau

    21. November 2013 um 7:50 Uhr


  • Schützt ein Include-Wächter nicht genau vor dieser Sache?

    – obskyr

    20. April 2017 um 14:06 Uhr

  • @obskyr nein, Include Guards schützen nicht davor. Include-Wächter verhindern lediglich, dass dieselbe Header-Datei mehrmals in eine einzelne Quelldatei eingefügt wird. Es verhindert nicht, dass dieser Header in mehreren Quelldateien angezeigt wird. Sie hätten also immer noch das Problem, dass mehrere Quellen dieselbe Variable definiert haben.

    – iheanyi

    4. März 2021 um 19:11 Uhr

Benutzeravatar von aib
aib

Es wurde bereits gesagt, dass die extern Schlüsselwort ist für Funktionen redundant.

Variablen, die von mehreren Kompilierungseinheiten gemeinsam genutzt werden, sollten Sie in einer Header-Datei mit dem Schlüsselwort extern deklarieren und sie dann in einer einzigen Quelldatei ohne das Schlüsselwort extern definieren. Als Best Practice sollte die einzelne Quelldatei diejenige sein, die den Namen der Header-Datei teilt.

  • @aib “redundant für Funktionen”, überprüfen Sie meinen Kommentar in der Antwort von bluebrother.

    – rsjethani

    11. August 2013 um 14:15 Uhr

  • Was ist, wenn Sie keine der Funktionen in der Header-Datei verfügbar machen möchten? Wäre es nicht besser, die Variable in einer C-Datei zu deklarieren und in einer anderen über extern darauf zuzugreifen? Lassen Sie den Linker das Problem lösen und den Rest des Headers ausblenden.

    – ste3e

    27. Januar 2014 um 5:32 Uhr

Benutzeravatar von Christian Gingras
Christian Ginger

Viele Jahre später entdecke ich diese Frage. Nachdem ich jede Antwort und jeden Kommentar gelesen hatte, dachte ich, ich könnte ein paar Details klären … Dies könnte für Leute nützlich sein, die über die Google-Suche hierher gelangen.

Die Frage bezieht sich speziell auf die Verwendung extern Funktionen, daher werde ich die Verwendung von ignorieren extern mit globalen Variablen.

Lassen Sie uns 3 Funktionsprototypen definieren:

// --------------------------------------
// Filename: "my_project.H"
extern int function_1(void);
static int function_2(void);
       int function_3(void);

Die Header-Datei kann vom Hauptquellcode wie folgt verwendet werden:

// --------------------------------------
// Filename: "my_project.C"
#include "my_project.H"

void main(void) {
    int v1 = function_1();
    int v2 = function_2();
    int v3 = function_3();
}

int function_2(void) return 1234;

Um zu kompilieren und zu verknüpfen, müssen wir definieren function_2 in derselben Quellcodedatei, in der wir diese Funktion aufrufen. Die beiden anderen Funktionen könnten in einem anderen Quellcode definiert werden *.C oder sie können sich in einer beliebigen Binärdatei befinden (*.OBJ, *.LIB, *.DLL), für die wir möglicherweise keinen Quellcode haben.

Lassen Sie uns wieder den Header einfügen my_project.H in einem anderen *.C Datei, um den Unterschied besser zu verstehen. Im selben Projekt fügen wir die folgende Datei hinzu:

// --------------------------------------
// Filename: "my_big_project_splitted.C"
#include "my_project.H"

void old_main_test(void){
    int v1 = function_1();
    int v2 = function_2();
    int v3 = function_3();
}

int function_2(void) return 5678;

int function_1(void) return 12;

int function_3(void) return 34;

Wichtige Merkmale zu beachten:

  • Wenn eine Funktion definiert ist als static in einer Header-Datei muss der Compiler/Linker eine Instanz einer Funktion mit diesem Namen in jedem Modul finden, das diese Include-Datei verwendet.

  • Eine Funktion, die Teil der C-Bibliothek ist, kann in nur einem Modul ersetzt werden, indem ein Prototyp mit neu definiert wird static nur in diesem Modul. Ersetzen Sie beispielsweise jeden Aufruf von malloc und free um die Funktion zur Erkennung von Speicherlecks hinzuzufügen.

  • Der Spezifizierer extern wird für Funktionen nicht wirklich benötigt. Wann static nicht gefunden wird, wird immer eine Funktion angenommen extern.

  • Jedoch, extern ist nicht die Standardeinstellung für Variablen. Normalerweise muss jede Header-Datei verwendet werden, die Variablen definiert, die in vielen Modulen sichtbar sein sollen extern. Die einzige Ausnahme wäre, wenn eine Header-Datei garantiert von einem und nur einem Modul enthalten ist.

    Viele Projektmanager würden dann verlangen, dass eine solche Variable am Anfang des Moduls platziert wird, nicht in einer Header-Datei. Einige große Projekte, wie der Videospiel-Emulator „Mame“, verlangen sogar, dass solche Variablen nur über der ersten Funktion erscheinen, die sie verwendet.

Benutzeravatar von Steve Melnikoff
Steve Melnikoff

In C, extern ist für Funktionsprototypen impliziert, da ein Prototyp eine Funktion deklariert, die woanders definiert ist. Mit anderen Worten, ein Funktionsprototyp hat standardmäßig eine externe Verknüpfung; verwenden extern ist in Ordnung, aber überflüssig.

(Wenn eine statische Verknüpfung erforderlich ist, muss die Funktion als deklariert werden static sowohl im Prototyp als auch im Funktionsheader, und diese sollten sich normalerweise beide in derselben .c-Datei befinden).

Benutzeravatar von qris
qris

Ein sehr guter Artikel, über den ich gekommen bin extern Stichwort, zusammen mit den Beispielen: http://www.geeksforgeeks.org/understanding-extern-keyword-in-c/

Obwohl ich damit nicht einverstanden bin extern in Funktionsdeklarationen ist überflüssig. Dies soll eine Compiler-Einstellung sein. Daher empfehle ich die Verwendung von extern in den Funktionsdeklarationen, wenn es benötigt wird.

Wenn jede Datei in Ihrem Programm zuerst zu einer Objektdatei kompiliert wird, dann werden die Objektdateien miteinander verknüpft, die Sie benötigen extern. Es sagt dem Compiler: “Diese Funktion existiert, aber der Code dafür ist woanders. Keine Panik.”

  • So läuft die Übersetzung normalerweise ab: Quelldateien werden zu Objektdateien kompiliert und dann verlinkt. Wann würden Sie in diesem Fall kein extern benötigen? Sie würden auch nicht #include verwenden, um Funktionen zu erhalten, sondern Funktionsprototypen. Ich verstehe nicht, wovon du redest.

    – David Thornley

    30. Januar 2009 um 17:56 Uhr

  • Ich scheine in letzter Zeit dieses Problem zu haben, Dinge falsch zu interpretieren. Das tut mir leid. Als ich neu in C war, #include “file.c”, um die Funktionen in einer Datei direkt in die andere Datei einzufügen. Dann habe ich herausgefunden, wie man ‘extern’ verwendet. Ich dachte, er macht den gleichen Fehler wie ich.

    – Chris Lutz

    30. Januar 2009 um 18:18 Uhr

1426890cookie-checkSo verwenden Sie das Schlüsselwort extern in C richtig

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

Privacy policy