1 Grundlegende Erklärung: extern kann vor einer Variablen oder Funktion platziert werden, um anzuzeigen, dass sich die Definition der Variablen oder Funktion in einer anderen Datei befindet, und fordert den Compiler auf, seine Definition in anderen Modulen zu finden, wenn er auf diese Variable oder Funktion stößt. Darüber hinaus kann extern auch zur Linkspezifikation verwendet werden.
Das heißt, extern hat zwei Funktionen, wenn es zusammen mit „C“ verwendet wird, wie zum Beispiel: extern „C“ void fun(int a, int b); Befolgen Sie beim Kompilieren des Funktionsnamens fun die Regeln von C, um den entsprechenden Funktionsnamen anstelle von C++ zu übersetzen. Die Regeln von C++ ändern den Namen fun bis zur Unkenntlichkeit, wenn er den Funktionsnamen übersetzt Möglicherweise ist es etwas anderes. Es hängt vom „Temperament“ des Compilers ab (verschiedene Compiler verwenden unterschiedliche Methoden), da C++ dieses Problem nicht zu sehr bespricht Wenn Sie interessiert sind, können Sie online suchen. Ich glaube, Sie können eine zufriedenstellende Erklärung erhalten!
Zweitens, wenn extern nicht zusammen mit „C“ verwendet wird, um Variablen oder Funktionen zu ändern, z. Die Funktion besteht darin, den Umfang von Funktionen oder globalen Variablen zu deklarieren. Denken Sie daran, dass es sich um eine Deklaration und nicht um eine Definition handelt ) Wenn Sie auf eine globale Variable oder Funktion verweisen, die im Modul (Kompilierungseinheit) A definiert ist, muss nur die Header-Datei von Modul A enthalten sein. Während der Kompilierungsphase kann Modul B die Funktion oder Variable zwar nicht finden, meldet jedoch keinen Fehler . Diese Funktion befindet sich im Objektcode, der beim Verknüpfen von Modul A generiert wird.
2 Frage: Die externe Variable
definiert ein Array in einer Quelldatei: char a[6] und deklariert es in einer anderen Datei mit der folgenden Anweisung: extern char *a; > Entschuldigung, ist das in Ordnung?
Antwort und Analyse:
1). Nein, das Programm meldet Ihnen illegale Zugriffe, wenn es ausgeführt wird. Der Grund dafür ist, dass ein Zeiger auf den Typ T nicht äquivalent zu einem Array vom Typ T ist. extern char *a deklariert eine Zeigervariable und kein Zeichenarray, unterscheidet sich also von der tatsächlichen Definition und führt zur Laufzeit zu illegalem Zugriff. Die Deklaration sollte in extern char a[ ] geändert werden.
2) Die Beispielanalyse lautet wie folgt. Wenn a[] = „abcd“, dann ist die externe Variable a = 0x61626364 (der ASCII-Codewert von abcd), *a ist offensichtlich bedeutungslos
Offensichtlich zeigt das Leerzeichen an a (0x61626364) bedeutet nicht, dass es zu illegalen Speicherzugriffen kommen kann.
3) Dies erinnert uns daran, dass wir uns bei der Verwendung von extern strikt an das Format der Deklaration halten müssen. In der tatsächlichen Programmierung kommen solche Fehler häufig vor.
4) Extern wird häufig in Variablendeklarationen verwendet. Wenn diese globale Variable referenziert werden soll, fügen Sie sie in *.h ein und verwenden Sie extern.
3 Problem: Wenn der Prototyp der externen Funktion geändert wird
Antwort und Analyse:
Derzeit verfügt die Branche nicht über eine perfekte Lösung für den Umgang mit dieser Situation. Der übliche Ansatz besteht darin, dass der Anbieter eine Deklaration der externen Schnittstelle in seiner eigenen xxx_pub.h bereitstellt und dann die Der Aufrufer schließt die Header-Datei ein, wodurch der externe Schritt entfällt. um diesen Fehler zu vermeiden.
Das Schwert hat zwei Schneiden, je nach Situation sollten unterschiedliche Methoden gewählt werden.
4 Problem: externes „C“
Antwort und Analyse:
Das Folgende ist eine Standardschreibweise:
//Am Kopf der .h-Datei
#ifdef __cplusplus
#if __cplusplus
extern "C"{
#endif
#endif/* __cplusplus */ #endif /* __cplusplus */
5 Frage: externe Funktionsdeklaration
Es kommt oft vor, dass extern vor einer Funktion steht und Teil der Funktionsdeklaration wird. Welche Rolle spielt also das C-Sprachschlüsselwort extern bei der Deklaration einer Funktion? ?
Antwort und Analyse:
Wenn das Schlüsselwort extern in der Deklaration einer Funktion enthalten ist, bedeutet dies nur, dass die Funktion möglicherweise in anderen Quelldateien definiert ist und keine weiteren Auswirkungen hat. Das heißt, es gibt keinen offensichtlichen Unterschied zwischen den folgenden beiden Funktionsdeklarationen:
extern int f(); und int f();
Dies ist natürlich immer noch nützlich, das heißt, um include „*“ zu ersetzen. h“ im Programm Um Funktionen zu deklarieren, bin ich es in einigen komplexen Projekten eher gewohnt, vor allen Funktionsdeklarationen externe Änderungen hinzuzufügen. Die Gründe und Vor- und Nachteile hierfür können im folgenden Beispiel gesehen werden: „Globale Variablen mit extern geändert“
(1) In test1.h gibt es die folgende Anweisung:
#ifndef TEST1H
#define TEST1H
extern char g_str[]; // Globale Variable g_str
void fun1();
#endif
(2) In test1.cpp
#include "test1 .h"
char g_str[] = "123456"; // Globale Variable g_str definieren
void fun1() { cout << g_str << endl; }
(3) Das Obige ist das Modul test1. Wenn wir auch das Modul test2 haben und g_str verwenden möchten, müssen wir es nur in der Originaldatei zitieren
#include „test1.h“
void fun2() { cout << g_str << Der obige Test1 und Test2 können gleichzeitig kompiliert und verbunden werden. obj, und Sie können die Zeichenfolge „123456“ darin finden, aber Sie können sie nicht in test2.obj finden. Dies liegt daran, dass g_str eine globale Variable im Speicher ist Die Kompilierungseinheit test2.obj benötigt keine weitere Kopie, da sie sonst während der Verbindung gemeldet wird. Dieser Fehler wird durch wiederholte Definitionen verursacht. (4) Manche Leute fügen die Deklaration und Definition globaler Variablen gerne zusammen Vergessen Sie die Definition, z. B. das Ändern des obigen test1.h in
extern char g_str[] = " 123456"; // Dies ist gleichbedeutend mit no extern
Entfernen Sie dann die Definition von g_str in test1.cpp Dieses Mal wird beim Kompilieren und Verbinden der beiden Module test1 und test2 ein Verbindungsfehler gemeldet. Dies liegt daran, dass Sie die globale Definition der Variablen g_str geändert haben. Das Modul test1.cpp enthält test1. h, also ist g_str einmal definiert, und test2.cpp enthält auch test1.h, also ist g_str erneut definiert. Zu diesem Zeitpunkt verbindet sich der Connector. In test1 und test2 wurden zwei g_str gefunden. Wenn Sie die Definition von g_str in test1.h einfügen müssen, entfernen Sie #include „test1.h“ aus dem Code von test2 und ersetzen Sie es durch:
extern char g_str[];
void fun2() { cout << g_str << }
Zu diesem Zeitpunkt weiß der Compiler, dass g_str ein externes Kompilierungsmodul ist und wird es in diesem Modul nicht erneut definieren Sehr schlecht, da #include „test1.h“ in test2.cpp nicht verwendet werden kann. Dann können Sie keine anderen in test1.h deklarierten Funktionen verwenden, es sei denn, sie werden ebenfalls mit extern geändert. In diesem Fall gibt es eine lange Liste deklarierter Funktionen Die Funktion ist allein, und die Funktion der Header-Datei besteht darin, Schnittstellen für den externen Gebrauch bereitzustellen. Denken Sie also bitte daran, Deklarationen nur in der Header-Datei vorzunehmen, die Wahrheit ist immer so einfach.
6. extern und statisch
(1) extern zeigt an, dass die Variable an anderer Stelle definiert wurde und dass diese Variable hier verwendet werden sollte.
(2) static zeigt an, dass die Variable statisch ist , Variablen werden im statischen Bereich gespeichert, nicht auf dem Stapel
Der Umfang von Static ist in gewisser Weise im Gegensatz zum externen Bereich. Er wird getrennt vom Objekt selbst gespeichert, und auch der externe Bereich ist getrennt. Gespeichert, aber extern kann von anderen Objekten als extern referenziert werden, statische jedoch nicht. Spezifische Unterschiede: Erstens sind static und extern ein Paar „inkompatibler“ Typen, was bedeutet, dass extern und static können eine Variable nicht gleichzeitig ändern; zweitens wird die durch static geänderte globale Variable gleichzeitig deklariert und definiert, dh wenn Sie static verwenden, um die globale Variable in der Header-Datei zu deklarieren, ist dies auch der Fall Gleichzeitig wird die Rolle einer statisch geänderten globalen Variablen definiert. Eine Domäne kann nur ihre eigene Kompilierungseinheit sein, was bedeutet, dass ihre „globale“ Funktion nur für diese Kompilierungseinheit gültig ist und andere Kompilierungseinheiten sie nicht sehen können, z :
#ifndef TEST1H
#define TEST1H
static char g_str[] = "123456";
void fun1();
#endif
(2) test1.cpp:
#include "test1.h"
void fun1() { cout << g_str <<
#include "test1.h"
void fun2() { cout << g_str << , Sie finden darin die Zeichenfolge „123456“ und sie können sie auch in test2.obj finden. Der Grund, warum sie erfolgreich verbunden werden können, ohne dass ein doppelter Definitionsfehler gemeldet wird, liegt darin, dass sie zwar denselben Inhalt haben, aber die physischen Daten gespeichert sind Adressen sind nicht gleich, genau wie zwei verschiedenen Variablen, denen derselbe Wert zugewiesen wird, und diese beiden Variablen wirken sich auf ihre jeweiligen Kompilierungseinheiten aus. Vielleicht meinen Sie es ernster und verfolgen und debuggen den obigen Code heimlich. Als Ergebnis stellen Sie fest, dass die Speicheradresse von g_str in den beiden Kompilierungseinheiten (test1, test2) gleich ist, sodass Sie daraus schließen, dass auch statisch geänderte Variablen funktionieren können auf anderen Modulen, aber ich möchte Ihnen sagen, dass Ihr Compiler Sie täuscht. Die meisten Compiler verfügen über Optimierungsfunktionen für den Code, um das Ziel zu erreichen, ein Zielprogramm zu generieren, das Speicher spart und eine höhere Ausführungseffizienz aufweist Kompilierungseinheiten. Manchmal wird nur eine Kopie des Speichers mit demselben Inhalt kopiert, z. B. „123456“ oben. Die Variablen in den beiden Kompilierungseinheiten haben denselben Inhalt, sodass beim Herstellen einer Verbindung nur eine Kopie im Speicher vorhanden ist . Wenn Sie nun den obigen Code wie folgt ändern, können Sie die Lügen des Compilers sofort aufdecken:
(1) test1.cpp:
#include "test1.h"
void fun1( )
{
g_str[0] = ''a'';
cout << g_str << endl;
}
(2) test2.cpp
void fun2() { cout << g_str << (3) void main() {
fun1(); 🎜> fun2(); // 123456
}
Wenn Sie den Code zu diesem Zeitpunkt verfolgen, werden Sie feststellen, dass die g_str-Adresse in den beiden Kompilierungseinheiten nicht identisch ist, da Sie sie an einer Stelle geändert haben. Daher ist der Compiler gezwungen, das ursprüngliche Erscheinungsbild des Speichers wiederherzustellen, und es gibt zwei Kopien für die Variablen in den beiden Modulen im Speicher. Gerade weil statische Variablen die oben genannten Eigenschaften aufweisen, werden sie bei der Definition statischer globaler Variablen im Allgemeinen in der Originaldatei und nicht in der Header-Datei abgelegt, um keine unnötige Informationsverschmutzung für andere Module zu verursachen. Denken Sie auch an dieses Prinzip!
7. extern und const
Durch const in C++ geänderte globale Konstanten haben die gleichen Eigenschaften wie static, das heißt, sie können nur in diesem kompilierten Modul verwendet werden, const kann jedoch mit verwendet werden extern Deklarieren Sie, dass diese Konstante in anderen kompilierten Modulen verwendet werden kann, z. B. extern const char g_str[];