Esto es útil cuando se necesita para acceder a una variable que reside dentro de otra unidad de traducción, sin exponer la variable externa a nivel mundial (por algunas razones, como la colisión de nombres, o que la variable del no debería ser directamente accedido, por lo que static
se usó para limitar su alcance, pero ese encabezado de TU aún necesita acceso).
A modo de ejemplo, digamos que tenemos una unidad de traducción foo.c
, que contiene:
//foo.c
static int i = 0;
i
No se debe cambiar o directamente acceder sin entrar en foo.c
, sin embargo, a lo largo de foo.h
viene requiriendo acceso a i
para una función en línea, pero i
no debe exponerse a ninguna unidad de traducción utilizando foo.h
, por lo que podemos usar extern
a nivel funcional, para exponerlo solo durante el alcance de IncI
, la función en línea que requiere el uso de i
:
//foo.h
inline void IncI(int val)
{
extern int i;
i += val;
}
Su segundo ejemplo es 'anulado' porque el compilador piensa que usted está tratando de unir dos variables diferentes para el mismo nombre de símbolo, es decir: se crea la static i
en el ámbito local, pero las búsquedas para el extern int i
en ámbito global, pero no lo encuentra, porque static i
como en el alcance de la función. un compilador más inteligente solo arreglaría el enlace al static i
, si esto sigue los estándares que yo no sabría.
Ahora que tengo un C standards document a trabajar a partir de (la culpa es mía lo sé ...), podemos ver lo que la postura oficial es (en C99):
6.2.2 Linkages of identifiers
Section 3:
If the declaration of a file scope identifier for an object or a function contains the storageclass specifier static, the identifier has internal linkage.
Section 4:
For an identifier declared with the storage-class specifier extern in a scope in which a prior declaration of that identifier is visible, if the prior declaration specifies internal or external linkage, the linkage of the identifier at the later declaration is the same as the linkage specified at the prior declaration. If no prior declaration is visible, or if the prior declaration specifies no linkage, then the identifier has external linkage.
así, porque static
causará un enlace interno, el extern
llevará ese enlace al alcance actual. también hay una nota que indica que esto puede causar escondite de variables:
23) As specified in 6.2.1, the later declaration might hide the prior declaration.
Porque 'i' es externo o local, no puede ser ambos. – Till
no permitido? Su segundo fragmento de código funciona perfectamente bien en mi gcc (mingw) –
Estoy usando gcc 4.1.2 20080704 (Red Hat 4.1.2-51) y me sale el siguiente error: file1.c: En la función âmainâ: file1.c : 6: error: declaración externa de âa sigue la declaración sin vinculación file1.c: 5: error: la definición anterior de âiâ estaba aquí – Bruce