Réponses:
Lorsque vous écrivez un fichier de mise en œuvre ( .cpp
, .cxx
, etc.) votre compilateur génère une unité de traduction . Il s'agit du fichier source de votre implémentation et de tous les en-têtes que vous y trouverez #include
.
Le lien interne fait référence à tout uniquement dans le cadre d'une unité de traduction .
Le lien externe fait référence à des choses qui existent au-delà d'une unité de traduction particulière. En d'autres termes, accessible via l'ensemble du programme , qui est la combinaison de toutes les unités de traduction (ou fichiers objets).
const
variables (ainsi que son objectif) est totalement manquée ici.
Comme le dit dudewat, le lien externe signifie que le symbole (fonction ou variable globale) est accessible dans tout votre programme et le lien interne signifie qu'il n'est accessible que dans une seule unité de traduction .
Vous pouvez contrôler explicitement la liaison d'un symbole à l'aide des mots clés extern
et static
. Si la liaison n'est pas spécifiée, la liaison par défaut est extern
pour les non- const
symboles et static
(interne) pour les const
symboles.
// 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
Notez qu'au lieu d'utiliser static
pour la liaison interne, il est préférable d'utiliser des espaces de noms anonymes dans lesquels vous pouvez également placer class
es. Le lien pour les espaces de noms anonymes a changé entre C ++ 98 et C ++ 11 mais l'essentiel est qu'ils sont inaccessibles à partir d'autres unités de traduction.
namespace {
int i; // external linkage but unreachable from other translation units.
class invisible_to_others { };
}
extern
déclaration correspondante dans l'autre fichier.static
. Ces variables auraient un lien interne .Prenons l'exemple suivant:
void f(int i);
extern const int max = 10;
int n = 0;
int main()
{
int a;
//...
f(a);
//...
f(a);
//...
}
f
déclare f
comme une fonction avec une liaison externe (par défaut). Sa définition doit être fournie ultérieurement dans ce fichier ou dans une autre unité de traduction (indiquée ci-dessous).max
est défini comme une constante entière. Le lien par défaut pour les constantes est interne . Son lien est changé en externe avec le mot-clé extern
. Alors maintenant, max
on peut y accéder dans d'autres fichiers.n
est défini comme une variable entière. Le lien par défaut pour les variables définies en dehors des corps de fonction est externe .#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
est déclaré avoir un lien externe . Une définition correspondante pour max
(avec liaison externe) doit apparaître dans certains fichiers. (Comme dans 1.cpp)n
est déclaré avoir un lien externe .z
est défini comme une variable globale avec un lien interne .nCall
spécifie nCall
être une variable qui conserve sa valeur lors des appels à la fonction f()
. Contrairement aux variables locales avec la classe de stockage automatique par défaut, nCall
sera initialisé une seule fois au démarrage du programme et pas une fois pour chaque appel de f()
. Le spécificateur de classe de stockage static
affecte la durée de vie de la variable locale et non sa portée.NB: Le mot-clé static
joue un double rôle. Lorsqu'il est utilisé dans les définitions des variables globales, il spécifie le lien interne . Lorsqu'il est utilisé dans les définitions des variables locales, il spécifie que la durée de vie de la variable va être la durée du programme au lieu d'être la durée de la fonction.
J'espère que cela pourra aider!
static
permet l'initialisation unique paresseuse (ce qui peut être utile si vous avez besoin d'un objet global-ish mais devez contrôler quand il est construit en raison de problèmes avec l'ordre de construction global et ne pouvez pas l'allouer dynamiquement l'utilisation de new
schémas d'initialisation plus approfondis peut être au-delà de ce qui est nécessaire pour l'objet en question; par implication, c'est principalement un problème sur les systèmes embarqués qui utilisent C ++).
Permet de parler de différentes portées en «C»
PORTÉE: C'est essentiellement combien de temps puis-je voir quelque chose et jusqu'où.
Variable locale: la portée est uniquement à l'intérieur d'une fonction. Il réside dans la zone STACK de RAM. Ce qui signifie que chaque fois qu'une fonction est appelée, toutes les variables qui font partie de cette fonction, y compris les arguments de fonction, sont fraîchement créées et sont détruites une fois que le contrôle quitte la fonction. (Parce que la pile est vidée à chaque retour de la fonction)
Variable statique: la portée de ceci est pour un fichier. Il est accessible partout dans le fichier
dans lequel il est déclaré. Il réside dans le segment DATA de RAM. Étant donné que cela n'est accessible qu'à l'intérieur d'un fichier et donc d'une liaison INTERNE. Aucun
autre fichier ne peut voir cette variable. En fait, le mot-clé STATIC est le seul moyen par lequel nous pouvons introduire un certain niveau de données ou de fonction se
cachant en «C»
Variable globale: la portée de ceci est pour une application entière. Il est accessible partout dans l'application. Les variables globales résident également dans le segment DATA puisqu’elles sont accessibles partout dans l’application et donc la liaison EXTERNE
Par défaut, toutes les fonctions sont globales. Dans le cas, si vous devez masquer certaines fonctions d'un fichier de l'extérieur, vous pouvez préfixer le mot-clé statique à la fonction. :-)
Avant de parler de la question, il est préférable de connaître précisément le terme unité de traduction , programme et certains concepts de base du C ++ (en fait, le lien est l'un d'entre eux). Vous devrez également savoir ce qu'est une portée .
Je soulignerai certains points clés, en particulier. ceux manquants dans les réponses précédentes.
Lien est une propriété d'un nom , qui est introduit par une déclaration . Différents noms peuvent désigner la même entité (généralement, un objet ou une fonction). Par conséquent, parler de liaison d'une entité est généralement un non-sens, sauf si vous êtes sûr que l'entité ne sera référencée que par le nom unique de certaines déclarations spécifiques (généralement une seule déclaration, cependant).
Notez qu'un objet est une entité, mais pas une variable . En parlant du lien d'une variable, en fait, le nom de l'entité désignée (qui est introduit par une déclaration spécifique) est concerné. Le lien du nom est dans l'un des trois: pas de lien, lien interne ou lien externe.
Différentes unités de traduction peuvent partager la même déclaration par en-tête / fichier source (oui, c'est le libellé de la norme). Vous pouvez donc faire référence au même nom dans différentes unités de traduction. Si le nom déclaré a un lien externe, l'identité de l'entité référencée par le nom est également partagée. Si le nom déclaré a un lien interne, le même nom dans différentes unités de traduction désigne différentes entités, mais vous pouvez référencer l'entité dans différentes étendues de la même unité de traduction. Si le nom n'a pas de lien, vous ne pouvez tout simplement pas référencer l'entité à partir d'autres étendues.
(Oups ... J'ai trouvé que ce que j'avais tapé répétait un peu la formulation standard ...)
Il existe également d'autres points déroutants qui ne sont pas couverts par la spécification de langue.
__attribute__
ou__declspec
) ou les options du compilateur, et l'image n'est pas le programme entier ou le fichier objet traduit à partir d'une unité de traduction, donc aucun concept standard ne peut le décrire avec précision. Le symbole n'étant pas un terme normatif en C ++, il ne s'agit que d'un détail d'implémentation, même si les extensions associées des dialectes peuvent avoir été largement adoptées.La règle de liaison de la const
variable de portée d'espace de noms est quelque chose de spécial (et particulièrement différent de l' const
objet déclaré dans la portée de fichier en langage C qui a également le concept de liaison des identificateurs). Étant donné que l' ODR est appliqué par C ++, il est important de ne pas conserver plus d'une définition de la même variable ou fonction dans le programme entier, à l'exception des inline
fonctions . S'il n'y a pas une telle règle spéciale const
, une déclaration de const
variable la plus simple avec des initialiseurs (par exemple, la variable comme remplacement de certaines macros de type objet est impossible.= xxx
) dans un en-tête ou un fichier source (souvent un "fichier d'en-tête") inclus par plusieurs unités de traduction (ou inclus par une unité de traduction plus d'une fois, bien que rarement) dans un programme violera ODR, ce qui rend l'utilisationconst
Je pense que le lien interne et externe en C ++ donne une explication claire et concise:
Une unité de traduction fait référence à un fichier d'implémentation (.c / .cpp) et à tous les fichiers d'en-tête (.h / .hpp) qu'elle inclut. Si un objet ou une fonction à l'intérieur d'une telle unité de traduction a une liaison interne, ce symbole spécifique n'est visible que par l'éditeur de liens au sein de cette unité de traduction. Si un objet ou une fonction a un lien externe, l'éditeur de liens peut également le voir lors du traitement d'autres unités de traduction. Le mot-clé statique, lorsqu'il est utilisé dans l'espace de noms global, force un symbole à avoir une liaison interne. Le mot-clé extern entraîne un symbole ayant un lien externe.
Le compilateur par défaut la liaison de symboles tels que:
Les variables globales non const ont un lien externe par défaut Les
variables globales Const ont un lien interne par défaut Les
fonctions ont un lien externe par défaut
La liaison détermine si les identifiants qui ont des noms identiques font référence au même objet, fonction ou autre entité, même si ces identifiants apparaissent dans différentes unités de traduction. Le lien d'un identifiant dépend de la façon dont il a été déclaré. Il existe trois types de liens:
C ++ uniquement : vous pouvez également établir une liaison entre des fragments de code C ++ et non C ++, ce qui est appelé liaison de langage .
Source: IBM Program Linkage
Fondamentalement
extern linkage
la variable est visible dans tous les fichiersinternal linkage
variable est visible dans un seul fichier.Expliquer: les variables const lient en interne par défaut, sauf indication contraire comme extern
external linkage
const
la variable globale estinternal linkage
extern const
la variable globale supplémentaire estexternal linkage
Un assez bon matériel sur la liaison en C ++
http://www.goldsborough.me/c/c++/linker/2016/03/30/19-34-25-internal_and_external_linkage_in_c++/
En C ++
Toute variable à portée de fichier et qui n'est pas imbriquée dans une classe ou une fonction, est visible dans toutes les unités de traduction d'un programme. C'est ce qu'on appelle un lien externe, car au moment du lien, le nom est visible partout par l'éditeur de liens, externe à cette unité de traduction.
Les variables globales et les fonctions ordinaires ont un lien externe.
L' objet statique ou le nom de fonction à la portée du fichier est local à l'unité de traduction. C'est ce qu'on appelle un lien interne
Le lien se réfère uniquement aux éléments qui ont des adresses au moment du lien / chargement; ainsi, les déclarations de classe et les variables locales n'ont aucun lien.