Antworten:
Wenn Sie eine Implementierungsdatei ( ,, usw.) schreiben .cpp
, .cxx
generiert Ihr Compiler eine Übersetzungseinheit . Dies ist die Quelldatei aus Ihrer Implementierung sowie alle darin enthaltenen Header #include
.
Interne Verknüpfung bezieht sich auf alles nur im Rahmen einer Übersetzungseinheit .
Externe Verknüpfung bezieht sich auf Dinge, die jenseits einer bestimmten Übersetzungseinheit existieren. Mit anderen Worten, Zugriff über das gesamte Programm , dh die Kombination aller Übersetzungseinheiten (oder Objektdateien).
const
Variablen (sowie deren Zweck) hier völlig übersehen wird.
Wie dudewat sagte, bedeutet externe Verknüpfung, dass das Symbol (Funktion oder globale Variable) in Ihrem gesamten Programm zugänglich ist, und interne Verknüpfung bedeutet, dass nur in einer Übersetzungseinheit darauf zugegriffen werden kann .
Sie können die Verknüpfung eines Symbols mithilfe der Schlüsselwörter extern
und explizit steuern static
. Wenn die Verknüpfung nicht angegeben ist, gilt die Standardverknüpfung extern
für Nicht- const
Symbole und static
(intern) für const
Symbole.
// in namespace or global scope
int i; // extern by default
const int ci; // static by default
extern const int eci; // explicitly extern
static int si; // explicitly static
// the same goes for functions (but there are no const functions)
int foo(); // extern by default
static int bar(); // explicitly static
Beachten Sie, dass es static
für die interne Verknüpfung besser ist, anonyme Namespaces zu verwenden, in die Sie auch es class
einfügen können. Die Verknüpfung für anonyme Namespaces hat sich zwischen C ++ 98 und C ++ 11 geändert, aber die Hauptsache ist, dass sie von anderen Übersetzungseinheiten nicht erreichbar sind.
namespace {
int i; // external linkage but unreachable from other translation units.
class invisible_to_others { };
}
extern
Deklaration in der anderen Datei angegeben wird.static
. Solche Variablen sollen eine interne Verknüpfung haben .Betrachten Sie folgendes Beispiel:
void f(int i);
extern const int max = 10;
int n = 0;
int main()
{
int a;
//...
f(a);
//...
f(a);
//...
}
f
wird f
als Funktion mit externer Verknüpfung deklariert (Standard). Die Definition muss später in dieser Datei oder in einer anderen Übersetzungseinheit (siehe unten) angegeben werden.max
ist als ganzzahlige Konstante definiert. Die Standardverknüpfung für Konstanten ist intern . Die Verknüpfung wird mit dem Schlüsselwort in external geändert extern
. So max
kann jetzt in anderen Dateien zugegriffen werden.n
ist als ganzzahlige Variable definiert. Die Standardverknüpfung für Variablen, die außerhalb von Funktionskörpern definiert sind, ist extern .#include <iostream>
using namespace std;
extern const int max;
extern int n;
static float z = 0.0;
void f(int i)
{
static int nCall = 0;
int a;
//...
nCall++;
n++;
//...
a = max * z;
//...
cout << "f() called " << nCall << " times." << endl;
}
max
wird für eine externe Verknüpfung deklariert . Eine passende Definition für max
(mit externer Verknüpfung) muss in einer Datei enthalten sein. (Wie in 1.cpp)n
wird für eine externe Verknüpfung deklariert .z
ist definiert als eine globale Variable mit interner Bindung .nCall
gibt nCall
an, dass es sich um eine Variable handelt, die ihren Wert über Funktionsaufrufe hinweg beibehält f()
. Im Gegensatz zu lokalen Variablen mit der Standardklasse für die automatische Speicherung nCall
wird sie nur einmal zu Beginn des Programms und nicht einmal bei jedem Aufruf von initialisiert f()
. Der Speicherklassenspezifizierer static
beeinflusst die Lebensdauer der lokalen Variablen und nicht deren Umfang.NB: Das Schlüsselwort static
spielt eine doppelte Rolle. Bei Verwendung in den Definitionen globaler Variablen wird die interne Verknüpfung angegeben . Bei Verwendung in den Definitionen der lokalen Variablen wird angegeben, dass die Lebensdauer der Variablen die Dauer des Programms und nicht die Dauer der Funktion ist.
Ich hoffe, das hilft!
static
eine verzögerte Einzelinitialisierung möglich ist (was nützlich sein kann, wenn Sie ein globales Objekt benötigen, aber aufgrund von Problemen mit der globalen Konstruktionsreihenfolge steuern müssen, wann es erstellt wird, und es nicht dynamisch zuordnen können Die Verwendung von new
detaillierteren Initialisierungsschemata kann über das hinausgehen, was für das betreffende Objekt erforderlich ist. Dies ist implizit hauptsächlich ein Problem bei eingebetteten Systemen, die C ++ verwenden.
Sprechen wir über verschiedene Bereiche in 'C'
GELTUNGSBEREICH: Es ist im Grunde genommen, wie lange ich etwas sehen kann und wie weit.
Lokale Variable: Der Bereich befindet sich nur innerhalb einer Funktion. Es befindet sich im STACK-Bereich des RAM. Dies bedeutet, dass jedes Mal, wenn eine Funktion aufgerufen wird, alle Variablen, die Teil dieser Funktion sind, einschließlich der Funktionsargumente, neu erstellt und zerstört werden, sobald das Steuerelement die Funktion verlässt. (Weil der Stapel jedes Mal geleert wird, wenn die Funktion zurückkehrt)
Statische Variable: Der Gültigkeitsbereich bezieht sich auf eine Datei. Es ist überall in der Datei zugänglich,
in der es deklariert ist. Es befindet sich im DATA-Segment des RAM. Da darauf nur innerhalb einer Datei und damit der INTERNEN Verknüpfung zugegriffen werden kann. Jegliche
andere Dateien können diese Variable nicht sehen. Tatsächlich ist das Schlüsselwort STATIC die einzige Möglichkeit, Daten oder Funktionen einzuführen,
die in 'C' versteckt sind.
Globale Variable: Der Geltungsbereich gilt für eine gesamte Anwendung. Es ist von jedem Ort der Anwendung aus zugänglich. Globale Variablen befinden sich auch im DATA-Segment, da überall in der Anwendung darauf zugegriffen werden kann und somit EXTERNAL Linkage
Standardmäßig sind alle Funktionen global. Wenn Sie einige Funktionen in einer Datei von außen ausblenden müssen, können Sie der Funktion das statische Schlüsselwort voranstellen. :-)
Bevor Sie über die Frage sprechen, ist es besser, den Begriff Übersetzungseinheit , Programm und einige grundlegende Konzepte von C ++ (tatsächlich ist die Verknüpfung eines davon im Allgemeinen) genau zu kennen. Sie müssen auch wissen, was ein Bereich ist .
Ich werde einige wichtige Punkte hervorheben, insb. diejenigen, die in früheren Antworten fehlen.
Verknüpfung ist eine Eigenschaft eines Namens , die durch eine Deklaration eingeführt wird . Unterschiedliche Namen können dieselbe Entität bezeichnen (normalerweise ein Objekt oder eine Funktion). Es ist also normalerweise Unsinn, über die Verknüpfung einer Entität zu sprechen , es sei denn, Sie sind sicher, dass die Entität nur mit dem eindeutigen Namen aus bestimmten Deklarationen (normalerweise jedoch einer Deklaration) referenziert wird.
Beachten Sie, dass ein Objekt eine Entität ist, eine Variable jedoch nicht. Während über die Verknüpfung einer Variablen gesprochen wird, ist tatsächlich der Name der bezeichneten Entität (die durch eine bestimmte Deklaration eingeführt wird) betroffen. Die Verknüpfung des Namens erfolgt in einer der drei: keine Verknüpfung, interne Verknüpfung oder externe Verknüpfung.
Verschiedene Übersetzungseinheiten können dieselbe Deklaration nach Header- / Quelldatei (ja, dies ist der Wortlaut des Standards) enthalten. Sie können also denselben Namen in verschiedenen Übersetzungseinheiten verwenden. Wenn der deklarierte Name eine externe Verknüpfung aufweist, wird auch die Identität der Entität, auf die sich der Name bezieht, freigegeben. Wenn der deklarierte Name eine interne Verknüpfung aufweist, bezeichnet derselbe Name in verschiedenen Übersetzungseinheiten verschiedene Entitäten. Sie können die Entität jedoch in verschiedenen Bereichen derselben Übersetzungseinheit referenzieren. Wenn der Name keine Verknüpfung aufweist, können Sie die Entität einfach nicht aus anderen Bereichen referenzieren.
(Ups ... Ich habe festgestellt, dass das, was ich eingegeben habe, nur die Standardformulierung wiederholt ...)
Es gibt auch einige andere verwirrende Punkte, die in der Sprachspezifikation nicht behandelt werden.
__attribute__
oder__declspec
) oder Compileroptionen, und das Bild ist nicht das gesamte Programm oder die Objektdatei, die von einer Übersetzungseinheit übersetzt wurde. Daher kann kein Standardkonzept es genau beschreiben. Da Symbol in C ++ kein normativer Begriff ist, handelt es sich nur um ein Implementierungsdetail, obwohl die damit verbundenen Erweiterungen von Dialekten möglicherweise weit verbreitet sind.Die Verknüpfungsvorschrift von Namespacebereich const
variabel ist etwas Besonderes (und vor allem anders als das const
Objekt in Dateigültigkeitsbereich in C - Sprache erklärt , die auch das Konzept der Verknüpfung von Identifikatoren hat). Da ODR von C ++ erzwungen wird, ist es wichtig, dass nicht mehr als eine Definition derselben Variablen oder Funktion im gesamten Programm außer den inline
Funktionen beibehalten wird . Wenn es keine solche Sonderregel von gibt const
, ist eine einfachste Deklaration von const
Variablen mit Initialisierern (zB= xxx
) in einem Header oder einer Quelldatei (häufig eine "Header-Datei"), die von mehreren Übersetzungseinheiten (oder von einer Übersetzungseinheit mehr als einmal) enthalten wird. obwohl selten) in einem Programm wird ODR verletzen, die zu verwenden machtconst
Variable als Ersatz einiger objektähnlicher Makros unmöglich.
Ich denke, die interne und externe Verknüpfung in C ++ gibt eine klare und präzise Erklärung:
Eine Übersetzungseinheit bezieht sich auf eine Implementierungsdatei (.c / .cpp) und alle darin enthaltenen Headerdateien (.h / .hpp). Wenn ein Objekt oder eine Funktion innerhalb einer solchen Übersetzungseinheit eine interne Verknüpfung aufweist, ist dieses spezifische Symbol nur für den Linker innerhalb dieser Übersetzungseinheit sichtbar. Wenn ein Objekt oder eine Funktion über eine externe Verknüpfung verfügt, kann der Linker diese auch bei der Verarbeitung anderer Übersetzungseinheiten sehen. Das statische Schlüsselwort erzwingt bei Verwendung im globalen Namespace die interne Verknüpfung eines Symbols. Das Schlüsselwort extern führt zu einem Symbol mit externer Verknüpfung.
Der Compiler verwendet standardmäßig die Verknüpfung von Symbolen wie folgt:
Globale Variablen ohne
Konstante haben standardmäßig
eine externe Verknüpfung. Globale Variablen von Konstanten haben standardmäßig eine interne Verknüpfung. Funktionen haben standardmäßig eine externe Verknüpfung
Die Verknüpfung bestimmt, ob Bezeichner mit identischen Namen auf dasselbe Objekt, dieselbe Funktion oder eine andere Entität verweisen, selbst wenn diese Bezeichner in verschiedenen Übersetzungseinheiten angezeigt werden. Die Verknüpfung eines Bezeichners hängt davon ab, wie er deklariert wurde. Es gibt drei Arten von Verknüpfungen:
Nur C ++ : Sie können auch eine Verknüpfung zwischen C ++ - und Nicht-C ++ - Codefragmenten herstellen, die als Sprachverknüpfung bezeichnet wird .
Quelle: IBM Program Linkage
Grundsätzlich
extern linkage
Variable ist in allen Dateien sichtbarinternal linkage
Variable ist in einer einzelnen Datei sichtbar.Erklären Sie: const-Variablen werden standardmäßig intern verknüpft, sofern nicht anders als extern deklariert
external linkage
const
globale Variable istinternal linkage
extern const
globale Variable istexternal linkage
Ein ziemlich gutes Material zur Verknüpfung in C ++
http://www.goldsborough.me/c/c++/linker/2016/03/30/19-34-25-internal_and_external_linkage_in_c++/
In C ++
Jede Variable im Dateibereich, die nicht in einer Klasse oder Funktion verschachtelt ist, ist in allen Übersetzungseinheiten eines Programms sichtbar. Dies wird als externe Verknüpfung bezeichnet, da der Name zum Zeitpunkt der Verknüpfung für den Linker überall außerhalb dieser Übersetzungseinheit sichtbar ist.
Globale Variablen und gewöhnliche Funktionen sind extern verknüpft.
Der statische Objekt- oder Funktionsname im Dateibereich ist lokal für die Übersetzungseinheit. Das nennt man interne Verknüpfung
Die Verknüpfung bezieht sich nur auf Elemente, deren Adressen zum Zeitpunkt der Verknüpfung / Ladung vorliegen. Daher haben Klassendeklarationen und lokale Variablen keine Verknüpfung.