c++ c static global-variables

Variables estáticas en C y C++



static global-variables (5)

C y C ++ son lo mismo.

La estática hace dos cosas diferentes.

Para las variables declaradas fuera del alcance de una función, cambia la visibilidad (vinculación) 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 con esto pueda acceder a él (es posible que tenga que declararlo externo). Si la variable está fuera del alcance de una función y es estática, sigue siendo una variable global en el sentido de que siempre existe y mantiene 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 ella.

Para las variables declaradas dentro del alcance de una función, static cambia la ubicación donde se almacena la variable. Si no es estático, será una variable automática, eso significa que desaparece a medida que la función sale y vuelve a existir (en la pila) cuando la función se ingresa nuevamente. Este pierde su valor al salir de la función. Y también cualquier referencia a él (los punteros a él) son inválidas después de que la función sale. Si una variable declarada dentro del alcance de una función es estática, entonces no la convierte en una variable automática sino en una asignada globalmente. Por lo tanto, la variable existirá después de que la función salga y, por lo tanto, mantendrá su valor a través de las invocaciones de la función y también todas las referencias (indicadores) son válidas incluso después de que la función sale. 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 a ella directamente (sino solo a través de una referencia guardada) desde fuera del alcance de la función.

Una última cosa que hace la estática es cambiar cuando se ejecuta el inicializador (es decir, int foo = 5) para la variable. Para todos los casos donde 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, por lo que puede obtener un resultado no esperado si su inicializador no es solo un número constante, sino que también 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 es después de que se haya ingresado main ().

¿Hay alguna diferencia entre una variable declarada como static fuera de cualquier función entre C y C ++? Leí que static significa que el 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?


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

Fuera de una función, la palabra clave se refiere al vínculo, en el interior se refiere a la asignación. Todas las variables fuera de una función tienen una asignación estática implícita. Un diseño desafortunado quizás, pero ahí está.


No es realmente una respuesta directa a su pregunta, sino algo muy relacionado con lo que debe tener cuidado si usa tanto C como C ++.

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

Ejemplo:

// file A extern const int glob; // file B const int glob = 42;

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


No, no hay diferencia entre C y C ++ a este respecto.

Lea esta respuesta SO sobre lo que significa static en un programa en 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).

Con respecto a los vars globales que son static , solo desde el punto de vista de la asignación de memoria (se asignan en el segmento de datos, como lo son 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'')


Quiero agregar a la respuesta de Southern Hospitality las variables estáticas en C y C ++

los siguientes comentarios:

El uso de static para indicar "local a la unidad de traducción" está en desuso en C ++ (href = "https://rads..com/amzn/click/com/0201700735" rel = "nofollow noreferrer" El lenguaje de programación C ++: especial Edición, Apéndice B.2.3, Características desaprobadas).

Deberías usar espacios de nombres sin nombre en su lugar:

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

Como ya dijo Southern Hospitality, el orden de inicialización de los objetos globales no está definido. En esa situación, debe considerar el uso del patrón href = "http://en.wikipedia.org/wiki/Singleton_pattern#C.2B.2B", Singleton.

ACTUALIZACIÓN: GMan comentó mi respuesta:

"El orden se define por unidad de traducción, ...": Esto realmente me olvidó, así que lo busqué en el lenguaje de programación C ++.

En la Sección 9.4.1, Inicialización de variables no locales, el Prof. Stroustrup 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''; }

En mi opinión, esto es muy similar al patrón Singleton.

GMan comentó: "Necesitamos limitar nuestra capacidad para crear estos objetos a uno y proporcionarle acceso global". ¿La limitación a uno realmente se relaciona con algo en el problema? Podemos necesitar uno globalmente, pero ¿quién puede decir que no lo queremos en otros lugares?

Algunas citas de Singleton (127) (Gamma et al, Design Patterns):

"El patrón Singleton es una mejora sobre las variables globales. Evita contaminar el espacio de nombres con variables globales que almacenan instancias únicas".

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

Los Singletons se inicializan en el orden en que se usan por primera vez.

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

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

Por eso uso a menudo Singletons para evitar datos globales. Pero, por supuesto, como todo se puede abusar, esto podría ser un uso excesivo del patrón de Singleton. (Johshua Kerievsky llama a esto "Singletonitis" en su libro "Refactoring to Patterns".)

ACTUALIZACIÓN 2:

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

Jalf escribió en su comentario: "La pandilla de cuatro estaba fumando algo ilegal cuando escribieron sobre el patrón de singleton".

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

"Cuando necesite una variable (de nivel de espacio de nombres) que pueda depender de otra, considere el patrón de diseño de Singleton; si lo usa con cuidado, podría evitar las dependencias implícitas al garantizar que un objeto se inicialice en el primer acceso. Sin embargo, Singleton es una variable global en ropa de oveja, y se rompe por mutuas o dependencias cíclicas ".

Entonces, evita los datos globales, si puedes. 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 no existen datos globales. Obviamente, los datos globales se sustituyen / emulan mediante el uso del patrón de diseño Singleton.

(Porque trabajo en mi trabajo diario con un equipo de Java, me esfuerzo por lograr una similitud máxima de mis programas de C ++ con los programas de Java. Por ejemplo, cada clase se encuentra en su propio archivo fuente / unidad de traducción).