Especificar duración de almacenamiento y enlace de objetos y funciones:

  • auto – duración automática y sin vinculación
  • register – duración automática y sin vinculación; la dirección de esta variable no se puede tomar
  • static – static duración y vinculación interna (a menos que esté en el alcance del bloque)
  • extern – static duración y vinculación externa (a menos que ya se haya declarado interna)
  • _Thread_local – duración del almacenamiento del hilo
(desde C11)

Explicación

Los especificadores de clase de almacenamiento aparecen en declaraciones. Se puede usar como máximo un especificador, excepto eso _Thread_local puede combinarse con static o extern para ajustar la vinculación(desde C11). Los especificadores de la clase de almacenamiento determinan dos propiedades independientes de los nombres que declaran: duración de almacenamiento y enlace.

1) los auto El especificador solo está permitido para objetos declarados en el alcance del bloque (excepto las listas de parámetros de función). Indica la duración del almacenamiento automático y sin vinculación, que son los valores predeterminados para este tipo de declaraciones.2) los register El especificador solo está permitido para objetos declarados en el alcance del bloque, incluidas las listas de parámetros de función. Indica la duración del almacenamiento automático y sin vinculación (que es el valor predeterminado para este tipo de declaraciones), pero además sugiere al optimizador que almacene el valor de esta variable en un registro de la CPU si es posible. Independientemente de si esta optimización tiene lugar o no, las variables declaradas register no se puede utilizar como argumentos para el operador de dirección de, no puedo usar alignas(desde C11), y register las matrices no se pueden convertir en punteros.3) los static el especificador especifica ambos static duración de almacenamiento (a menos que se combine con _Thread_local)(desde C11) y vinculación interna (a menos que se utilice en el alcance del bloque). Se puede usar con funciones en el alcance del archivo y con variables en el alcance del archivo y del bloque, pero no en las listas de parámetros de función.4) los extern especificador especifica static duración de almacenamiento (a menos que se combine con _Thread_local)(desde C11) y vinculación externa. Se puede utilizar con declaraciones de funciones y objetos tanto en el ámbito de archivo como en el de bloque (excluyendo listas de parámetros de función). Si extern aparece en una redeclaración de un identificador que ya fue declarado con enlace interno, el enlace permanece interno. De lo contrario (si la declaración anterior fue externa, sin vinculación o no está dentro del alcance), la vinculación es externa.

5)_Thread_local indica duración del almacenamiento del hilo. No se puede utilizar con declaraciones de funciones. Si se utiliza en una declaración de un objeto, debe estar presente en cada declaración del mismo objeto. Si se usa en una declaración de alcance de bloque, debe combinarse con static o extern para decidir la vinculación. (desde C11)

Si no se proporciona un especificador de clase de almacenamiento, los valores predeterminados son:

extern para todas las funciones
extern para objetos en el alcance del archivo
auto para objetos en el alcance del bloque

Para cualquier estructura o unión declarada con un especificador de clase de almacenamiento, la duración del almacenamiento (pero no el enlace) se aplica a sus miembros, de forma recursiva.

Las declaraciones de funciones en el alcance del bloque pueden usar extern o ninguno en absoluto. Las declaraciones de funciones en el ámbito del archivo pueden usar extern o static.

Los parámetros de función no pueden utilizar ningún especificador de clase de almacenamiento que no sea register. Tenga en cuenta que static tiene un significado especial en los parámetros de función de array escribe.

Duración de almacenamiento

Cada objeto tiene una propiedad llamada duración de almacenamiento, que limita la vida útil del objeto. Hay cuatro tipos de duración de almacenamiento en C:

  • automático duración del almacenamiento. El almacenamiento se asigna cuando se ingresa el bloque en el que se declaró el objeto y se desasigna cuando se sale por cualquier medio (goto, return, llegando al final). Una excepción son los VLA; su almacenamiento se asigna cuando se ejecuta la declaración, no en la entrada del bloque, y se desasigna cuando la declaración sale del alcance, no cuando se sale del bloque(desde C99). Si el bloque se ingresa de forma recursiva, se realiza una nueva asignación para cada nivel de recursividad. Todos los parámetros de función y nostatic Los objetos de alcance de bloque tienen esta duración de almacenamiento, así como los literales compuestos utilizados en el alcance de bloque.
    • static duración del almacenamiento. La duración del almacenamiento es la ejecución completa del programa, y ​​el valor almacenado en el objeto se inicializa solo una vez, antes de la función principal. Todos los objetos declarados static y todos los objetos con vinculación interna o externa que no están declarados _Thread_local(desde C11) tienen esta duración de almacenamiento.
  • hilo duración del almacenamiento. La duración del almacenamiento es la ejecución completa del subproceso en el que se creó, y el valor almacenado en el objeto se inicializa cuando se inicia el subproceso. Cada hilo tiene su propio objeto distinto. Si el hilo que ejecuta la expresión que accede a este objeto no es el hilo que ejecutó su inicialización, el comportamiento está definido por la implementación. Todos los objetos declarados _Thread_local tienen esta duración de almacenamiento.
(desde C11)
  • asignado duración del almacenamiento. El almacenamiento se asigna y desasigna a pedido, utilizando funciones de asignación de memoria dinámica.

Enlace

La vinculación se refiere a la capacidad de un identificador (variable o función) para ser referido en otros ámbitos. Si una variable o función con el mismo identificador se declara en varios ámbitos, pero no se puede hacer referencia a todos ellos, se generan varias instancias de la variable. Se reconocen los siguientes vínculos:

  • sin vinculación. Se puede hacer referencia al identificador solo desde el ámbito en el que se encuentra. Todos los parámetros de función y todos losextern variables de alcance de bloque (incluidas las declaradas static) tienen este vínculo.
    • vinculación interna. Se puede hacer referencia al identificador desde todos los ámbitos de la unidad de traducción actual. Todos static Los identificadores de ámbito de archivo (tanto funciones como variables) tienen este vínculo.
    • enlace externo. Se puede hacer referencia al identificador desde cualquier otra unidad de traducción en todo el programa. Todos los nostatic funciones, todas extern variables (a menos que se hayan declarado anteriormente static), y todos los archivos de alcance que no seanstatic las variables tienen este vínculo.

Si aparece el mismo identificador con enlaces internos y externos en la misma unidad de traducción, el comportamiento no está definido. Esto es posible cuando se utilizan definiciones provisionales.

Vinculación y bibliotecas

Las declaraciones con enlace externo suelen estar disponibles en archivos de encabezado para que todas las unidades de traducción que # incluyen el archivo puedan hacer referencia al mismo identificador que se define en otro lugar.

Cualquier declaración con vínculo interno que aparezca en un archivo de encabezado da como resultado un objeto distinto y separado en cada unidad de traducción que incluye ese archivo.

Interfaz de biblioteca:

// flib.h#ifndefFLIB_H#defineFLIB_Hvoidf(void);// function declaration with external linkageexternint state;// variable declaration with external linkagestaticconstint size =5;// definition of a read-only variable with internal linkageenum MAX =10;// constant definitioninlineintsum(int a,int b)return a+b;// inline function definition#endif// FLIB_H

Implementación de la biblioteca:

// flib.c#include"flib.h"staticvoidlocal_f(int s)// definition with internal linkage (only used in this file)staticint local_state;// definition with internal linkage (only used in this file)int state;// definition with external linkage (used by main.c)voidf(void)local_f(state);// definition with external linkage (used by main.c)

Código de aplicación:

// main.c #include"flib.h"intmain(void)int x[MAX]=size;// uses the constant and the read-only variable
    state =7;// modifies state in flib.cf();// calls f() in flib.c

Palabras clave

auto, register, static, extern, _Thread_local.

Notas

La palabra clave _Thread_local se usa generalmente por conveniencia macro thread_local, definido en el encabezado threads.h.

El especificador typedef se enumera formalmente como un especificador de clase de almacenamiento en la gramática del lenguaje C, pero se usa para declarar nombres de tipos y no especifica el almacenamiento.

Nombres en el ámbito del archivo que son const y no extern tienen enlace externo en C (como predeterminado para todas las declaraciones de alcance de archivo), pero enlace interno en C ++.

Ejemplo

#include#include/* static storage duration */int A;intmain(void)printf("&A = %pn",(void*)&A);/* automatic storage duration */int A =1;// hides global Aprintf("&A = %pn",(void*)&A);/* allocated storage duration */int*ptr_1 =malloc(sizeof(int));/* start allocated storage duration */printf("address of int in allocated memory = %pn",(void*)ptr_1);free(ptr_1);/* stop allocated storage duration  */

Salida posible:

&A =0x600ae4&A =0x7ffefb064f5c
address of int in allocated memory =0x1f28c30

Referencias

  • Estándar C11 (ISO / IEC 9899: 2011):
    • 6.2.2 Vínculos de identificadores (p: 36-37)
    • 6.2.4 Duraciones de almacenamiento de objetos (p: 38-39)
    • 6.7.1 Especificadores de clase de almacenamiento (p: 109-110)
  • Estándar C99 (ISO / IEC 9899: 1999):
    • 6.2.2 Vínculos de identificadores (p: 30-31)
    • 6.2.4 Duraciones de almacenamiento de objetos (p: 32)
    • 6.7.1 Especificadores de clase de almacenamiento (p: 98-99)
  • Estándar C89 / C90 (ISO / IEC 9899: 1990):
    • 3.1.2.2 Vínculos de identificadores
    • 3.1.2.4 Duraciones de almacenamiento de objetos
    • 3.5.1 Especificadores de clase de almacenamiento

Ver también