2010-03-27 23 views
15

¿Hay alguna diferencia entre una variable declarada como static fuera de cualquier función entre C y C++. Leí que static significa alcance del archivo y las variables no serán accesibles fuera del archivo. También leí que en C, las variables globales son static. Entonces, ¿eso significa que no se puede acceder a las variables globales en C en otro archivo?Las variables estáticas en C y C++

Respuesta

16

No, no hay ninguna diferencia entre C y C++ en este sentido.

Leer this SO answer acerca de lo que significa static en un programa C. En C++ hay un par de otros significados relacionados con el uso de static para variables de clase (en lugar de variables de instancia).

En cuanto a los valores globales es static - solo desde el punto de vista de la asignación de memoria (se asignan en el segmento de datos, como todos los globales). Desde el punto de vista de la visibilidad:.

static int var; // can't be seen from outside files 
int var;   // can be seen from outside files (no 'static') 
+0

Entonces, ¿cómo puedo acceder a una variable fuera del archivo en C? 'extern' no funcionará con' static' ¿verdad? puede ser que estoy demasiado confundido .. – Naveen

+0

@Naveen: no hay problema, * a menos que * lo haya declarado 'estático' –

+0

Ok ... así que en el segundo caso, ¿cuál será la clase de almacenamiento para la variable' var'? ¿Hay algún nombre para él o simplemente se llama variable global? – Naveen

7

Hay dos conceptos aquí "estática vinculación (o alcance)" y asignación estática"

fuera de una función de la palabra clave se refiere a la vinculación, dentro de él se refiere a la asignación. Todas las variables fuera de una función tienen asignación estática implícitamente. un diseño desafortunado tal vez, pero no lo es.

5

C y C++ son los mismos.

estática hace dos cosas diferentes.

Para las variables declarados fuera de un ámbito de función, cambia la visibilidad (ligamiento) de la variable. La variable será una variable global ya que está fuera del alcance de una función. Si no es estático, tendrá un enlace universal (visibilidad) para que cualquier código vinculado entre sí pueda acceder a él (puede que tenga que declararlo extern). Si la variable está fuera de un alcance de función y es estática, sigue siendo una variable global, ya que siempre existe y conserva su valor, pero ningún código fuera de la misma unidad de compilación (ese archivo .c y cualquier .h incluido) puede acceder a él.

Para las variables declaradas dentro de un ámbito de la función, los cambios estáticos la ubicación donde se almacena la variable. Si no es estático, será una variable automática, eso significa que desaparece cuando la función sale y vuelve a existir (en la pila) cuando se vuelve a ingresar la función. Esto pierde su valor cuando salgas de la función. Y también cualquier referencia al mismo (punteros) no es válida después de que la función finalice. Si una variable declarada dentro de un alcance de función es estática, no la convierte en una variable automática sino en una asignada globalmente. Entonces la variable existirá después de que la función salga y así mantendrá su valor a través de las invocaciones de la función y también cualquier referencia (punteros) a esta será válida incluso después de que la función finalice. Tenga en cuenta que, en ambos casos, el alcance de la variable solo está dentro de esa función, por lo que no es posible acceder directamente (pero solo a través de una referencia guardada) desde fuera del alcance de la función.

Una última cosa estática hace es cambio cuando el inicializador (es decir int foo = 5) para que se ejecute la variable. Para todos los casos en que la asignación es global (todos los casos, excepto el automático), el inicializador se ejecuta solo una vez, al comienzo de la ejecución de su programa. Se ejecuta antes de que main() se ejecute incluso, de modo que puede obtener un resultado no esperado si su inicializador no es solo un número constante, sino que ejecuta algún código. Para el caso automático, el inicializador se ejecuta cada vez que se ingresa la función, y en este caso siempre ocurre después de que se haya ingresado main().

+0

¿Está seguro de que las variables estáticas dentro de una función se inicializan antes de main()? Siempre pensé que se inicializaron la primera vez que se llamó a la función, y eso también es lo que dicen las respuestas aquí: http://stackoverflow.com/questions/246564/what-is-the-lifetime-of-a-static-variable -in-ac-function –

+0

Las respuestas en ese hilo son para C++. Supongo que mi suposición de que C y C++ lo hacen de la misma manera es incorrecto.Algunos buscando dicen que C solo permite inicializadores constantes y que se llenan en tiempo de compilación, no en tiempo de ejecución. Entonces eso es antes de main() para mi crédito. Pero estaba equivocado sobre el resto, C++ lo hace de manera diferente y, por lo tanto, todos los casos que importan deben interpretarse de acuerdo con el enlace que insertó. –

1

Quiero añadir a la respuesta de la hospitalidad del sur Static variables in C and C++

las siguientes observaciones:

El uso de static para indicar "local a la unidad de traducción" está en desuso en C++ (href = "http: // rads.stackoverflow.com/amzn/click/0201700735 "El lenguaje de programación C++: edición especial, apéndice B.2.3, características desaprobadas".

Debe utilizar espacios de nombres sin nombre en su lugar:

static int reply = 42; // deprecated 

namespace { 
    int reply1 = 42; // The C++ way 
} 

Como ya se ha dicho por la hospitalidad del sur, el orden de inicialización de objetos globales no está definido. En esa situación, debería considerar usar el patrón href = "http://en.wikipedia.org/wiki/Singleton_pattern#C.2B.2B", Singleton.

ACTUALIZACIÓN: GMan comentado mi respuesta:

"El orden se define por unidad-traducción, ...": Esto realmente se me olvidó, así que busqué en el directorio C++ Programming Language.

En la Sección 9.4.1, inicialización de variables no locales, Prof. BS sugiere que "una función que devuelve una referencia es una buena alternativa a una variable global":

int& use_count() 
{ 
     static int uc = 0; 
     return uc; 
} 

"Una llamada a use_count() ahora actúa como una variable global que se inicializa en su primer uso. Por ejemplo:"

void f() 
{ 
     std::cout << ++use_count() << '\n'; 
} 

a mi entender, esto es muy similar al patrón Singleton.

GMan comentó adicionalmente: "Necesitamos limitar nuestra capacidad de crear estos objetos a uno y proporcionar acceso global a él". ¿La limitación a uno realmente se relaciona con algo en el problema? Es posible que tengamos uno a nivel mundial, pero ¿quién puede decir que no queremos que en otros lugares "

Algunas citas de Singleton (127) (Gamma et al, patrones de diseño):

"? El patrón Singleton es una mejora sobre las variables globales. Evita contaminar el espacio de nombres con las variables globales que almacenan los casos individuales."

'El patrón hace que sea fácil de cambiar de opinión y permitir que más de una instancia de la clase Singleton.'

Singleton se inicializan en el . orden en que se utilizaron por primera vez

En Herb Sutter, Andrei Alexandrescu, C++ estándares de codificación, artículo 10 dice:

"Evitar los datos compartidos, especialmente los datos globales."

Por lo tanto uso a menudo Singletons para evitar datos globales. Pero, por supuesto, como todo es usable, esto podría ser un uso excesivo del patrón de Singleton. (Johshua Kerievsky llama a esto "Singletonitis" en su libro "Refactoring a los patrones".)

ACTUALIZACIÓN 2:

(Lo siento, pero no puedo escribir comentarios, por lo tanto, esta actualización.)

Jalf escribió en su comentario: "La banda de los cuatro fumaba algo ilegal cuando escribieron sobre el patrón singleton".

Obviamente, otros desarrolladores de C++ también han fumado sustancias interesantes. Por ejemplo, Herb Sutter (trabajó durante más de una década como secretario y presidente del comité de normas ISO C++ durante el desarrollo del segundo estándar de C++, C++ 0x, y como arquitecto principal de C++/CLI en Microsoft. Herb está actualmente el diseñador del modelo de memoria Prism para plataformas Microsoft y las extensiones Concur para Visual C++ para programación paralela), escribió en C++ Coding Standards, artículo 21:

"Cuando se necesita una variable (nivel de espacio de nombres) que pueda depender otra, considere el patrón de diseño de Singleton: si se usa con cuidado, podría evitar dependencias implícitas al garantizar que un objeto se inicialice con el primer acceso. Aún así, Singleton es una variable global en la piel de oveja y está roto por dependencias cíclicas o mutuas ".

Por lo tanto, evite datos globales, si puede. Pero si tiene que usar datos globales en unidades de traducción separadas, Singleton debería ser una solución aceptable para imponer una secuencia de inicialización específica.

Tenga en cuenta que en el lenguaje Java los datos globales ni siquiera existen. Obviamente, los datos globales son sustituidos/emulados por el uso del patrón de diseño de Singleton.

(Por lo cual estoy trabajando en mi dayjob con un equipo de Java, me esfuerzo para una máxima similitud de mis C++ programas con los programas Java. Por ejemplo, todas las clases se encuentra en su propia unidad de archivo de origen/traducción.)

+0

El orden se define por unidad de traducción, por lo que vale. Pero espero que vea que el patrón singleton no es la solución. "El orden de inicialización entre unidades no está especificado" -> "Necesitamos limitar nuestra capacidad de crear estos objetos a uno y proporcionar acceso global a él". ¿La limitación a uno realmente se relaciona con algo en el problema? Es posible que necesitemos uno * globalmente *, pero ¿quién puede decir que no lo queremos en otros lugares? – GManNickG

+2

@edit: Singletons son datos globales, no importa cómo lo vista. También puede eliminar las restricciones innecesarias y crear un contenedor global. http://jalf.dk/blog/2010/03/singletons-solving-problems-you-didnt-know-younever-had-since-1995/ – GManNickG

+1

¿Cómo tiene sentido su cita de Gamma et al? Las instancias globales no contaminan más un espacio de nombres que los singletons. (tome 'std :: cout' como ejemplo. Una instancia global, visible en el espacio de nombres estándar. ¿Cómo es su función' f' mejor? Que a es visible en el espacio de nombres en el que está declarado. En cuanto a la segunda parte, no, los singleton hacen ** mucho más difícil * cambiar de opinión. Toda su base de código está llena de llamadas a getInstance() o acceso implícito de datos estáticos. Estoy de acuerdo con mi conclusión: la banda de los cuatro estaba fumando algo ilegal cuando escribieron sobre el patrón singleton. – jalf

0

No es realmente una respuesta directa a su pregunta, pero algo estrechamente relacionado a tener en cuenta si usa tanto C como C++.

En C++, a diferencia de C, las variables globales que se declaran "const" son implícitamente locales para la unidad de traducción, AS SI se ha utilizado "estático".

Ejemplo:

// file A 
extern const int glob; 

// file B 
const int glob = 42; 

Esto funcionará si está utilizando un compilador C, pero no con un compilador de C++. En C++, la variable glob en el archivo B no se puede usar desde el archivo A y el enlazador generará un error de "referencia no resuelta".

Cuestiones relacionadas