2010-05-15 22 views
46

¿Por qué extern int n no se compila cuando n se declara (en un archivo diferente) static int n, pero funciona cuando se declara int n? (Ambas declaraciones estaban en el alcance del archivo).¿Por qué no se vincula externamente a una variable estática?

Básicamente, ¿por qué int n en el alcance 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?

Respuesta

97

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

Tenga en cuenta que hay cuatro sabores de archivos ámbito de definición de variables:

  1. int blah = 0; - bla se definen en este archivo y accesibles desde otros archivos. Las definiciones en otros archivos son duplicados y darán lugar a errores.
  2. extern int blah; - blah debe definirse en cualquier otro lugar y se hace referencia a este archivo.
  3. int blah; - Este es el equivalente moral de FORTRAN COMMON. Puede tener cualquier cantidad de estos en los archivos, y el vinculador los resuelve a uno compartido int. (*)
  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 puede tener muchos archivos diferentes que declaran static TYPE blah;, y todos son diferentes.

Para los puristas de la audiencia: 'archivo' = unidad de compilación.

Tenga en cuenta que las funciones internas estáticas (no en el alcance del archivo) son aún más estrictas: si dos funciones declaran static int bleh = 0; incluso en el mismo archivo, no están relacionadas.

(*): para aquellos que no están familiarizados: en el patrón habitual, una unidad de compilación tiene que definir una variable global, y otros pueden hacer referencia a ella. 'Vive' en esa unidad de compilació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 único int global y hace que todo el código se refiera a él.

+0

¿cómo se llamaría 'int n' (en el alcance del archivo), en términos de especificadores de almacenamiento? –

+0

@bmargulies: ¿En el alcance del archivo, quieres decir? Porque en el alcance de la función, una var estática es aquella que conserva su valor después de que las funciones regresen, y en el alcance de la clase, un miembro estático tiene una única instancia disponible para todos los objetos. – mingos

+0

Aclarado por la edición, confío. – bmargulies

5

En la norma C, hay dos ámbitos para las variables declaradas fuera de una función. Una variable static solo está visible dentro de la unidad de compilación (es decir, el archivo) que la declaró, y las variables no estáticas son visibles en todo el programa. Una declaración 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 extern static es una locura!

Por supuesto, en la práctica hay otras visibilidades en estos días. En particular, ahora hay niveles de alcance entre el de un solo archivo fuente y un programa 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.

0

De acuerdo con la documentación de MSDN:

When modifying a variable, the static keyword specifies that the variable has static duration (it is allocated when the program begins and deallocated when the program ends) and initializes it to 0 unless another value is specified. When modifying a variable or function at file scope, the static keyword specifies that the variable or function has internal linkage (its name is not visible from outside the file in which it is declared).

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

1

IV.C: 2: 1: Error: múltiples clases de almacenamiento en los especificadores de declaración extern static int i; ^

Eso es lo que obtenemos al tratar de externar una variable estática. Declarar extern static int i; - es análogo a la declaración float int i; No puede tener float e int aparecen en la misma declaración ¿no? Del mismo modo, no puede tener extern y static en la misma declaración.

Cuestiones relacionadas