Respuestas:
Cuando se escribe un archivo de aplicación ( .cpp
, .cxx
, etc.) el compilador genera una unidad de traducción . Este es el archivo fuente de su implementación más todas las cabeceras que #include
incluyó en él.
Enlace interno se refiere a todo solo en el alcance de una unidad de traducción .
La vinculación externa se refiere a cosas que existen más allá de una unidad de traducción particular. En otras palabras, accesible a través de todo el programa , que es la combinación de todas las unidades de traducción (o archivos de objetos).
const
variables (así como su propósito) se pierde por completo aquí.
Como dudewat, dicho enlace externo significa que el símbolo (función o variable global) es accesible a través de su programa y el enlace interno significa que solo es accesible en una unidad de traducción .
Puede controlar explícitamente el enlace de un símbolo utilizando las palabras clave extern
y static
. Si no se especifica el enlace, el enlace predeterminado es extern
para los que no son const
símbolos y static
(interno) para los const
símbolos.
// 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
Tenga en cuenta que en lugar de usar static
para enlaces internos, es mejor usar espacios de nombres anónimos en los que también puede poner class
es. El enlace para espacios de nombres anónimos ha cambiado entre C ++ 98 y C ++ 11, pero lo principal es que no se puede acceder desde otras unidades de traducción.
namespace {
int i; // external linkage but unreachable from other translation units.
class invisible_to_others { };
}
extern
declaración coincidente en el otro archivo.static
. Dichas variables se dice que tienen enlace interno .Considere el siguiente ejemplo:
void f(int i);
extern const int max = 10;
int n = 0;
int main()
{
int a;
//...
f(a);
//...
f(a);
//...
}
f
declara f
como una función con enlace externo (predeterminado). Su definición se debe proporcionar más adelante en este archivo o en otra unidad de traducción (se proporciona a continuación).max
se define como una constante entera. El enlace predeterminado para las constantes es interno . Su enlace se cambia a externo con la palabra clave extern
. Entonces ahora max
se puede acceder en otros archivos.n
se define como una variable entera. El enlace predeterminado para las variables definidas fuera de los cuerpos de función es externo .#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
se declara que tiene enlace externo . max
Debe aparecer una definición coincidente para (con enlace externo) en algún archivo. (Como en 1.cpp)n
se declara que tiene enlace externo .z
se define como una variable global con enlace interno .nCall
especifica nCall
que es una variable que retiene su valor en las llamadas a la función f()
. A diferencia de las variables locales con la clase de almacenamiento automático predeterminada, nCall
se inicializarán solo una vez al inicio del programa y no una vez por cada invocación de f()
. El especificador de clase de almacenamiento static
afecta la vida útil de la variable local y no su alcance.NB: la palabra clave static
juega un doble papel. Cuando se usa en las definiciones de variables globales, especifica el enlace interno . Cuando se usa en las definiciones de las variables locales, especifica que la vida útil de la variable será la duración del programa en lugar de ser la duración de la función.
¡Espero que ayude!
static
permite una inicialización simple perezosa (que puede ser útil si necesita un objeto global-ish pero tiene que controlar cuándo se construye debido a problemas con el orden de construcción global y no puede asignarlo dinámicamente) el uso de new
esquemas de inicialización más profundos puede estar más allá de lo necesario para el objeto en cuestión; por implicación, esto es principalmente un problema en los sistemas integrados que usan C ++).
Hablemos de diferentes alcances en 'C'
ALCANCE: Básicamente es cuánto tiempo puedo ver algo y qué tan lejos.
Variable local: el alcance solo está dentro de una función. Reside en el área STACK de RAM. Lo que significa que cada vez que se llama a una función, todas las variables que forman parte de esa función, incluidos los argumentos de la función, se crean recientemente y se destruyen una vez que el control sale de la función. (Debido a que la pila se vacía cada vez que regresa la función)
Variable estática: el alcance de esto es para un archivo. Es accesible desde cualquier lugar del archivo
en el que se declara. Reside en el segmento de DATOS de RAM. Dado que esto solo se puede acceder dentro de un archivo y, por lo tanto, enlace interno. Cualquier
otro archivo no puede ver esta variable. De hecho, la palabra clave STATIC es la única forma en que podemos introducir algún nivel de datos o función que se
oculta en 'C'
Variable global: el alcance de esto es para una aplicación completa. Es accesible desde cualquier lugar de la aplicación. Las variables globales también residen en el segmento DATOS, ya que se puede acceder a todas las partes de la aplicación y, por lo tanto, a la vinculación EXTERNA
Por defecto, todas las funciones son globales. En caso de que necesite ocultar algunas funciones en un archivo desde el exterior, puede anteponer la palabra clave estática a la función. :-)
Antes de hablar sobre la pregunta, es mejor conocer el término unidad de traducción , programa y algunos conceptos básicos de C ++ (en realidad, el enlace es uno de ellos en general) con precisión. También tendrá que saber qué es un alcance .
Destacaré algunos puntos clave, especialmente. los que faltan en respuestas anteriores.
La vinculación es una propiedad de un nombre , que se introduce mediante una declaración . Diferentes nombres pueden denotar la misma entidad (típicamente, un objeto o una función). Por lo tanto, hablar sobre la vinculación de una entidad generalmente no tiene sentido, a menos que esté seguro de que la entidad solo se referirá con el nombre único de algunas declaraciones específicas (por lo general, una declaración).
Tenga en cuenta que un objeto es una entidad, pero una variable no lo es. Al hablar sobre el enlace de una variable, en realidad se refiere al nombre de la entidad denotada (que se introduce mediante una declaración específica). El enlace del nombre se encuentra en uno de los tres: sin enlace, enlace interno o enlace externo.
Las diferentes unidades de traducción pueden compartir la misma declaración por encabezado / archivo fuente (sí, es la redacción del estándar) inclusión. Entonces puede referir el mismo nombre en diferentes unidades de traducción. Si el nombre declarado tiene un enlace externo, también se comparte la identidad de la entidad referida por el nombre. Si el nombre declarado tiene un enlace interno, el mismo nombre en diferentes unidades de traducción denota diferentes entidades, pero puede referir la entidad en diferentes ámbitos de la misma unidad de traducción. Si el nombre no tiene vinculación, simplemente no puede referir la entidad desde otros ámbitos.
(Vaya ... descubrí que lo que escribí fue algo así como repetir la redacción estándar ...)
También hay otros puntos confusos que no están cubiertos por la especificación del idioma.
__attribute__
o__declspec
) u opciones del compilador, y la imagen no es todo el programa o el archivo objeto traducido desde una unidad de traducción, por lo que ningún concepto estándar puede describirlo con precisión. Dado que símbolo no es un término normativo en C ++, es solo un detalle de implementación, a pesar de que las extensiones relacionadas de dialectos pueden haber sido ampliamente adoptadas.La regla de vinculación de la const
variable de alcance del espacio de nombres es algo especial (y particularmente diferente al const
objeto declarado en el alcance del archivo en lenguaje C que también tiene el concepto de vinculación de identificadores). Dado que C ++ aplica ODR , es importante mantener no más de una definición de la misma variable o función que se produjo en todo el programa, excepto para las inline
funciones . Si no existe dicha regla especial de const
, una declaración de const
variable más simple con inicializadores (p = xxx
. Ej. ) En un encabezado o un archivo fuente (a menudo un "archivo de encabezado") incluido por varias unidades de traducción (o incluido por una unidad de traducción más de una vez, aunque rara vez) en un programa violará ODR, lo que hace que el usoconst
variable como el reemplazo de algunas macros similares a objetos es imposible.
Creo que la vinculación interna y externa en C ++ da una explicación clara y concisa:
Una unidad de traducción se refiere a un archivo de implementación (.c / .cpp) y todos los archivos de encabezado (.h / .hpp) que incluye. Si un objeto o función dentro de dicha unidad de traducción tiene un enlace interno, entonces ese símbolo específico solo es visible para el enlazador dentro de esa unidad de traducción. Si un objeto o función tiene un enlace externo, el enlazador también puede verlo al procesar otras unidades de traducción. La palabra clave estática, cuando se usa en el espacio de nombres global, obliga a un símbolo a tener un enlace interno. La palabra clave externa da como resultado un símbolo que tiene un enlace externo.
El compilador predetermina el enlace de símbolos de manera que:
Las variables globales no constantes tienen un vínculo externo por defecto Las variables globales no constantes tienen un vínculo
interno por defecto Las
funciones tienen un vínculo externo por defecto
La vinculación determina si los identificadores que tienen nombres idénticos se refieren al mismo objeto, función u otra entidad, incluso si esos identificadores aparecen en diferentes unidades de traducción. El enlace de un identificador depende de cómo se declaró. Hay tres tipos de enlaces:
Solo C ++ : también puede tener una vinculación entre fragmentos de código C ++ y no C ++, lo que se denomina vinculación de lenguaje .
Fuente: Enlace de programa de IBM
Básicamente
extern linkage
variable es visible en todos los archivosinternal linkage
La variable es visible en un solo archivo.Explique: las variables const se vinculan internamente de forma predeterminada a menos que se declare como externo
external linkage
const
la variable global esinternal linkage
extern const
la variable global esexternal linkage
Un material bastante bueno sobre vinculación en C ++
http://www.goldsborough.me/c/c++/linker/2016/03/30/19-34-25-internal_and_external_linkage_in_c++/
En C ++
Cualquier variable en el alcance del archivo y que no esté anidada dentro de una clase o función, es visible en todas las unidades de traducción de un programa. Esto se llama enlace externo porque en el momento del enlace el nombre es visible para el enlazador en todas partes, externo a esa unidad de traducción.
Las variables globales y las funciones ordinarias tienen un enlace externo.
El objeto estático o el nombre de la función en el alcance del archivo es local para la unidad de traducción. Eso se llama Enlace interno
La vinculación se refiere solo a elementos que tienen direcciones en el enlace / tiempo de carga; por lo tanto, las declaraciones de clase y las variables locales no tienen vinculación.