¿Qué significa" estático " en C?


He visto la palabra static usada en diferentes lugares del código C; ¿es esto como una función/clase estática en C# (donde la implementación se comparte entre objetos)?

Author: jww, 2009-02-21

18 answers

  1. Una variable estática dentro de una función mantiene su valor entre invocaciones.
  2. Una variable global estática o una función se "ve" solo en el archivo que se declara en

(1) es el tema más extraño si eres un novato, así que aquí hay un ejemplo:

#include <stdio.h>

void foo()
{
    int a = 10;
    static int sa = 10;

    a += 5;
    sa += 5;

    printf("a = %d, sa = %d\n", a, sa);
}


int main()
{
    int i;

    for (i = 0; i < 10; ++i)
        foo();
}

Esto imprime:

a = 15, sa = 15
a = 15, sa = 20
a = 15, sa = 25
a = 15, sa = 30
a = 15, sa = 35
a = 15, sa = 40
a = 15, sa = 45
a = 15, sa = 50
a = 15, sa = 55
a = 15, sa = 60

Esto es útil para los casos en los que una función necesita mantener algún estado entre invocaciones, y no desea usar variables globales. Tenga cuidado, sin embargo, esta característica se debe utilizar con mucha moderación, hace que su código no sea seguro para subprocesos y sea más difícil de entender.

(2) Se utiliza ampliamente como una función de "control de acceso". Si tienes una .archivo c implementando alguna funcionalidad, por lo general expone solo unas pocas funciones "públicas" a los usuarios. El resto de sus funciones deben hacerse static, para que el usuario no pueda acceder a ellas. Esto es encapsulación, una buena práctica.

Citando Wikipedia:

En el lenguaje de programación C, estático se utiliza con variables globales y funciones para establecer su alcance a la conteniendo el archivo. En variables locales, static se utiliza para almacenar la variable en la memoria estáticamente asignada en lugar de la asignación automática memoria. Mientras que el idioma no dictar la implementación de cualquiera de los dos tipo de memoria asignada estáticamente la memoria se reserva típicamente en datos segmento del programa en compile tiempo, mientras que el automáticamente la memoria asignada es normalmente aplicada en una pila de llamadas transitorias.

Ver aquíy aquí para más detalles.

Y para responder a tu segunda pregunta, no es como en C#.

En C++, sin embargo, static también se usa para definir atributos de clase (compartidos entre todos los objetos de la misma clase) y métodos. En C no hay clases, por lo que esta característica es irrelevante.

 1247
Author: Eli Bendersky,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-08-12 14:25:29

Hay un uso más no cubierto aquí, y es como parte de una declaración de tipo array como argumento para una función:

int someFunction(char arg[static 10])
{
    ...
}

En este contexto, esto especifica que los argumentos pasados a esta función deben ser una matriz de tipo char con al menos 10 elementos en ella. Para más información vea mi pregunta aquí.

 193
Author: dreamlax,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 11:55:03

Respuesta Corta ... depende.

  1. Las variables locales definidas estáticas no pierden su valor entre llamadas a funciones. En otras palabras, son variables globales, pero con alcance a la función local en la que se definen.

  2. Las variables globales estáticas no son visibles fuera del archivo C en el que están definidas.

  3. Las funciones estáticas no son visibles fuera del archivo C en el que están definidas.

 142
Author: cmcginty,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-01-15 14:46:58

Ejemplo de ámbito de variable de varios archivos

A. c :

#include <stdio.h>

/*
Undefined behavior: already defined in main.
Binutils 2.24 gives an error and refuses to link.
https://stackoverflow.com/questions/27667277/why-does-borland-compile-with-multiple-definitions-of-same-object-in-different-c
*/
/*int i = 0;*/

/* Works in GCC as an extension: https://stackoverflow.com/a/3692486/895245 */
/*int i;*/

/* OK: extern. Will use the one in main. */
extern int i;

/* OK: only visible to this file. */
static int si = 0;

void a() {
    i++;
    si++;
    puts("a()");
    printf("i = %d\n", i);
    printf("si = %d\n", si);
    puts("");
}

Main.c :

#include <stdio.h>

int i = 0;
static int si = 0;

void a();    

void m() {
    i++;
    si++;
    puts("m()");
    printf("i = %d\n", i);
    printf("si = %d\n", si);
    puts("");
}

int main() {
    m();
    m();
    a();
    a();
    return 0;
}

Compilation :

gcc -c a.c -o a.o
gcc -c main.c -o main.o
gcc -o main main.o a.o

Salida:

m()
i = 1
si = 1

m()
i = 2
si = 2

a()
i = 3
si = 1

a()
i = 4
si = 2

Interpretación

  • hay dos variables separadas para si, una para cada archivo
  • hay una sola variable compartida para i

Como de costumbre, cuanto menor sea el alcance, mejor, por lo que siempre declare variables static si puedes.

En la programación en C, los archivos se utilizan a menudo para representar "clases", y static las variables representan miembros estáticos privados de la clase.

Qué dicen los estándares al respecto

C99 N1256 draft 6.7.1 "Especificadores de clase de almacenamiento" dice que static es un "especificador de clase de almacenamiento".

6.2.2 / 3 "Vínculos de identificadores" dice static implica internal linkage:

Si la declaración de un identificador de ámbito de archivo para un objeto o una función contiene el especificador de clase de almacenamiento estático, el identificador tiene enlace interno.

Y 6.2.2 / 2 dice que internal linkage se comporta como en nuestro ejemplo:

En el conjunto de unidades de traducción y bibliotecas que constituye un programa completo, cada declaración de un identificador particular con enlace externo denota el mismo objeto o función. Dentro de una unidad de traducción, cada declaración de un identificador con enlace interno denota el mismo objeto o función.

Donde "translation unit es un archivo fuente después del preprocesamiento.

¿Cómo lo implementa GCC para ELF (Linux)?

Con la unión STB_LOCAL.

Si compilamos:

int i = 0;
static int si = 0;

Y desmontar la tabla de símbolos con:

readelf -s main.o

La salida contiene:

Num:    Value          Size Type    Bind   Vis      Ndx Name
  5: 0000000000000004     4 OBJECT  LOCAL  DEFAULT    4 si
 10: 0000000000000000     4 OBJECT  GLOBAL DEFAULT    4 i

Así que la unión es la única diferencia significativa entre ellos. Value es solo su desplazamiento en la sección .bss, por lo que esperamos que difiera.

STB_LOCAL está documentado en la especificación ELF en http://www.sco.com/developers/gabi/2003-12-17/ch4.symtab.html :

STB_LOCAL Los símbolos locales no son visibles fuera del archivo objeto que contiene su definición. Los símbolos locales del mismo nombre pueden existir en varios archivos sin interferir entre sí

Lo que hace que sea una elección perfecta para representar static.

Las variables sin estática son STB_GLOBAL, y la especificación dice:

Cuando el enlace editor combina varios archivos objeto reubicables, no permite múltiples definiciones de símbolos STB_GLOBAL con el mismo nombre.

Que es coherente con los errores de enlace en múltiples definiciones no estáticas.

Si subimos la optimización con -O3, el símbolo si se elimina por completo de la tabla de símbolos: de todos modos, no se puede usar desde fuera. ¿Por qué mantener variables estáticas en la tabla de símbolos cuando no hay optimización? Pueden ser utilizados para ¿algo? Tal vez para depurar.

Véase también

Pruébalo tú mismo

Ejemplo en github para que juegues.

 47
Author: Ciro Santilli 新疆改造中心 六四事件 法轮功,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-01-19 10:51:52

Depende:

int foo()
{
   static int x;
   return ++x;
}

La función devolvería 1, 2, 3, etc. --- la variable no está en la pila.

A. c:

static int foo()
{
}

Significa que esta función solo tiene alcance en este archivo. Así que a. c y b.c pueden tener foo()s diferentes, y foo no está expuesto a objetos compartidos. Así que si definiste foo en a. c no podrías acceder desde b.c o desde cualquier otro lugar.

En la mayoría de las bibliotecas C todas las funciones "privadas" son estáticas y la mayoría de las "públicas" no lo son.

 33
Author: Artyom,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-03-28 17:13:57

La gente sigue diciendo que 'estático' en C tiene dos significados. Ofrezco una forma alternativa de verlo que le da un solo significado:

  • Aplicar 'static' a un elemento fuerza a ese elemento a tener dos propiedades: (a) No es visible fuera del ámbito actual; (b) Es persistente.

La razón por la que parece tener dos significados es que, en C, cada elemento al que se puede aplicar 'estático' ya tiene una de estas dos propiedades, por lo que parece como si el uso particular solo involucra al otro.

Por ejemplo, considere las variables. Las variables declaradas fuera de las funciones ya tienen persistencia (en el segmento de datos), por lo que aplicar 'static' solo puede hacer que no sean visibles fuera del ámbito actual (unidad de compilación). Por el contrario, las variables declaradas dentro de las funciones ya no tienen visibilidad fuera del ámbito actual (función), por lo que la aplicación de 'estática' solo puede hacerlas persistentes.

Aplicar 'estático' a las funciones es solo al igual que aplicarlo a variables globales, el código es necesariamente persistente (al menos dentro del lenguaje), por lo que solo se puede alterar la visibilidad.

NOTA: Estos comentarios solo se aplican a C. En C++, aplicar 'estático' a los métodos de clase realmente le da a la palabra clave un significado diferente. De manera similar para la extensión de argumento de matriz C99.

 18
Author: PMar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-04-27 13:47:26

static significa diferentes cosas en diferentes contextos.

  1. Puede declarar una variable estática en una función C. Esta variable solo es visible en la función, sin embargo, se comporta como un global, ya que solo se inicializa una vez y conserva su valor. En este ejemplo, cada vez que llame a foo() se imprimirá un número creciente. La variable estática se inicializa solo una vez.

    void foo ()
    {
    static int i = 0;
    printf("%d", i); i++
    }
    
  2. Otro uso de estática es cuando se implementa una función o global variable en a .archivo c pero no quiere que su símbolo sea visible fuera del .obj generado por el archivo. por ejemplo,

    static void foo() { ... }
    
 12
Author: m-sharp,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-11-17 13:43:25

De Wikipedia:

En el lenguaje de programación C, static se usa con variables y funciones globales para establecer su ámbito en el archivo que contiene. En las variables locales, la estática se usa para almacenar la variable en la memoria asignada estáticamente en lugar de la memoria asignada automáticamente. Si bien el lenguaje no dicta la implementación de ninguno de los dos tipos de memoria, la memoria asignada estáticamente se reserva típicamente en el segmento de datos del programa en compile tiempo, mientras que la memoria asignada automáticamente se implementa normalmente como una pila de llamadas transitorias.

 11
Author: OscarRyz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-02-21 06:52:18

Odio responder a una vieja pregunta, pero no creo que nadie haya mencionado cómo K&R lo explica en la sección A4.1 de "The C Programming Language".

En resumen, la palabra estática se usa con dos significados:

  1. Static es una de las dos clases de almacenamiento (la otra es automática). Un objeto estático mantiene su valor entre invocaciones. Los objetos declarados fuera de todos los bloques son siempre estáticos y no se pueden hacer automáticos.
  2. Pero, cuando el static palabra clave (gran énfasis en que se utiliza en code as a keyword) se usa con una declaración, le da a ese objeto un enlace interno para que solo se pueda usar dentro de esa unidad de traducción. Pero si la palabra clave se usa en una función, cambia la clase de almacenamiento del objeto (el objeto solo sería visible dentro de esa función de todos modos). Lo contrario de static es la palabra clave extern, que da un enlace externo al objeto.

Peter Van Der Linden da estos dos significados en " Experto Programación en C":

  • Dentro de una función, conserva su valor entre llamadas.
  • A nivel de función, visible solo en este archivo.
 6
Author: nobism,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-04-12 03:34:46

Si declara una variable en una función estática, su valor no se almacenará en la pila de llamadas a la función y seguirá estando disponible cuando vuelva a llamar a la función.

Si declara una variable global estática, su ámbito se restringirá al archivo en el que la declaró. Esto es un poco más seguro que un global regular que se puede leer y modificar a lo largo de todo el programa.

 5
Author: Sam Hoice,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-02-21 06:52:48

En C, static tiene dos significados, dependiendo del alcance de su uso. En el ámbito global, cuando se declara un objeto a nivel de archivo, significa que ese objeto solo es visible dentro de ese archivo.

En cualquier otro ámbito declara un objeto que conservará su valor entre las diferentes veces que se ingrese el ámbito en particular. Por ejemplo, si un int está delcared dentro de un procedimiento:

void procedure(void)
{
   static int i = 0;

   i++;
}

El valor de " i " se inicializa a cero en la primera llamada al procedimiento, y el el valor se conserva cada vez que se llama al procedimiento. si se imprimiera' i', produciría una secuencia de 0, 1, 2, 3,...

 5
Author: schot,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-09-25 13:07:06

Si usted declara esto en un mytest.archivo c:

static int my_variable;

Entonces esta variable solo se puede ver desde este archivo. La variable no se puede exportar a ningún otro lugar.

Si declara dentro de una función, el valor de la variable mantendrá su valor cada vez que se llame a la función.

Una función estática no se puede exportar desde fuera del archivo. Así que en un*.archivo c, está ocultando las funciones y las variables si las declara estáticas.

 4
Author: ant2009,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-03-18 16:49:02

Es importante tener en cuenta que las variables estáticas en las funciones se inicializan en la primera entrada en esa función y persisten incluso después de que su llamada haya terminado; en el caso de las funciones recursivas, la variable estática se inicializa solo una vez y persiste también sobre todas las llamadas recursivas e incluso después de que la llamada de la función haya terminado.

Si la variable se ha creado fuera de una función, significa que el programador solo puede usar la variable en el archivo fuente la variable ha sido declarada.

 3
Author: Starhowl,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-05-01 06:30:15

También hay que tener en cuenta que static se puede usar de 4 maneras diferentes.

to create permanent storage for local variables in a function.
to specify internal linkage.
to declare member functions that act like non-member functions.
to create a single copy of a data member.
 2
Author: amrx,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-01-06 23:03:28

Una variable estática es una variable especial que se puede usar en una función, y guarda los datos entre llamadas, y no los elimina entre llamadas. Por ejemplo:

void func(){
    static int count; // If you don't declare its value, the value automatically initializes to zero
    printf("%d, ", count);
    count++;
}

void main(){
    while(true){
        func();
    }
}

La salida:

0, 1, 2, 3, 4, 5, ...

 2
Author: Yagel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-03-28 17:16:23

Las variables estáticas en C tienen la vida útil del programa.

Si se definen en una función, tienen un alcance local, es decir, solo se puede acceder a ellas dentro de esas funciones. El valor de las variables estáticas se conserva entre llamadas a funciones.

Por ejemplo:

void function()
{
    static int var = 1;
    var++;
    printf("%d", var);
}

int main()
{
    function(); // Call 1
    function(); // Call 2
}

En el programa anterior, var se almacena en el segmento de datos. Su vida útil es todo el programa C.

Después de la llamada a la función 1, var se convierte en 2. Después de la llamada a la función 2, var se convierte 3.

El valor de var no se destruye entre llamadas a funciones.

Si var tuviera entre variable no estática y local, se almacenaría en el segmento de pila en el programa C. Dado que el marco de pila de la función se destruye después de que la función regresa, el valor de var también se destruye.

Las variables estáticas inicializadas se almacenan en el segmento de datos del programa C, mientras que las no inicializadas se almacenan en el segmento BSS.

Otra información acerca de static: Si una variable es global y estática, tiene el tiempo de vida del programa C, pero tiene alcance de archivo. Solo es visible en ese archivo.

Para probar esto:

File1.c

static int x;

int main()
{
    printf("Accessing in same file%d", x):
}

File2.c

    extern int x;
    func()
    {
        printf("accessing in different file %d",x); // Not allowed, x has the file scope of file1.c
    }

run gcc -c file1.c

gcc -c file2.c

Ahora intenta vincularlos usando:

gcc -o output file1.o file2.o

Daría un error de enlazador ya que x tiene el alcance del archivo file1.c y el enlazador no sería capaz de resolver la referencia a la variable x utilizada en file2.c.

Referencias:

  1. http://en.wikipedia.org/wiki/Translation_unit_ (programación)
  2. http://en.wikipedia.org/wiki/Call_stack
 2
Author: Sahil Manchanda,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-03-28 17:21:46

Un valor de variable estática persiste entre diferentes llamadas a funciones y su ámbito está limitado al bloque local un var estático siempre se inicializa con el valor 0

 1
Author: Jonathon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-03-23 05:48:32

Hay 2 casos:

(1) Variables locales declaradas static: Asignadas en segmento de datos en lugar de pila. Su valor se conserva cuando se vuelve a llamar a la función.

(2) Variables o funciones globales declaradas static: Invisibles fuera de la unidad de compilación (es decir, son símbolos locales en la tabla de símbolos durante el enlace).

 1
Author: Jonny Kong,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-06-03 13:01:49