¿Por qué no se vinculará externamente a una variable estática?

¿Por qué extern int n no se comstack cuando n se declara (en un archivo diferente) static int n , pero funciona cuando se declara int n ? (Ambas declaraciones estaban en el scope del archivo).

Básicamente, ¿por qué int n en el scope del archivo no es lo mismo que static int n en el mismo ámbito? ¿Es solo en relación con extern? Si es así, ¿qué tal extern me estoy perdiendo?

El objective completo y completo de static es declarar que una variable es privada para el archivo de origen en el que está declarada . Por lo tanto, está haciendo precisamente su trabajo para evitar una conexión desde un exterior.

Tenga en cuenta que hay cuatro formas de definición de variable de ámbito de archivo:

  1. int blah = 0; – blah se define en este archivo y se puede acceder desde otros archivos. Las definiciones en otros archivos son duplicados y darán lugar a errores.
  2. extern int blah; – blah debe definirse en otro lugar y se hace referencia a partir de este archivo.
  3. int blah; – Este es el equivalente moral de FORTRAN COMMON . Puede tener cualquier cantidad de estos en archivos, y el vinculador los resuelve en una sola int compartida. (*)
  4. static int blah; (opcionalmente con un inicializador) – Esto es estático. Es completamente privado para este archivo. No es visible para externos en otros archivos, y usted puede tener muchos archivos diferentes que declaren static TYPE blah; , y todos son diferentes .

Para los puristas en la audiencia: ‘archivo’ = unidad de comstackción .

Tenga en cuenta que las funciones internas estáticas (no en el scope del archivo) tienen un scope aún más estricto: si dos funciones declaran static int bleh = 0; incluso en el mismo archivo, no están relacionados.

(*): para aquellos que no están familiarizados: en el patrón habitual, una unidad de comstackción debe definir una variable global, y otras pueden hacer referencia a ella. ‘Vive’ en esa unidad de comstackción. En el caso (3), arriba, ningún archivo (o todos los archivos) lo define. Si dos archivos dicen int blah = 0; , el enlazador se quejará de múltiples definiciones. Si dos archivos dicen int blah; el enlazador crea alegremente un entero global único y hace que todo el código se refiera a él.

En el estándar C, hay dos ámbitos para las variables declaradas fuera de una función. Una variable static solo es visible dentro de la unidad de comstackción (es decir, archivo) que la declaró, y las variables no estáticas son visibles en todo el progtwig. Una statement extern dice que la ubicación de la variable aún no se conoce, pero será resuelta por el vinculador; es compatible con variables no estáticas, ¡pero la extern static es solo una locura!

Por supuesto, en la práctica hay otras visibilidades en estos días. En particular, ahora hay niveles de scope entre el de un solo archivo fuente y un progtwig completo; el nivel de una sola biblioteca compartida es útil (configurable a través de mecanismos como los atributos de la función GCC). Pero eso es solo una variación del tema de las variables no estáticas; static mantiene la misma interpretación que tenía antes.

iv.c: 2: 1: error: múltiples clases de almacenamiento en los especificadores de statement extern static int i; ^

Eso es lo que conseguimos tratando de externar una variable estática. Declarar extern static int i; – es análogo a la statement float int i; No puedes tener float e int aparecer en la misma statement ¿no? Del mismo modo, no puede tener extern y static en la misma statement.

De acuerdo con la documentación de MSDN:

Al modificar una variable, la palabra clave static especifica que la variable tiene una duración estática (se asigna cuando el progtwig comienza y se desasigna cuando termina el progtwig) y la inicializa a 0 a menos que se especifique otro valor. Al modificar una variable o función en el ámbito del archivo, la palabra clave estática especifica que la variable o función tiene una vinculación interna (su nombre no es visible desde fuera del archivo en el que se declara).

http://msdn.microsoft.com/en-us/library/s1sb61xd(v=vs.80).aspx : junio de 2013