C LanguageClases de almacenamiento


Introducción

Una clase de almacenamiento se usa para establecer el alcance de una variable o función. Al conocer la clase de almacenamiento de una variable, podemos determinar el tiempo de vida de esa variable durante el tiempo de ejecución del programa.

Sintaxis

  • [auto | register | static | extern] <Tipo de datos> <Nombre de variable> [= <Valor>];

  • [static _Thread_local | extern _Thread_local | _Thread_local] <Tipo de datos> <Nombre de variable> [= <Valor>]; / * desde> = C11 * /

  • Ejemplos:

  • typedef int foo ;

  • extern int foo [2];

Observaciones

Los especificadores de clase de almacenamiento son las palabras clave que pueden aparecer junto al tipo de declaración de nivel superior. El uso de estas palabras clave afecta la duración del almacenamiento y la vinculación del objeto declarado, dependiendo de si se declara en el alcance del archivo o en el alcance del bloque:

Palabra clave Duración del almacenamiento Enlace Observaciones
static Estático Interno Establece el enlace interno para los objetos en el alcance del archivo; establece la duración del almacenamiento estático para objetos en el ámbito de bloque.
extern Estático Externo Implícito y, por lo tanto, redundante para los objetos definidos en el alcance del archivo que también tienen un inicializador. Cuando se usa en una declaración en el alcance del archivo sin un inicializador, insinúa que la definición se encuentra en otra unidad de traducción y se resolverá en el momento del enlace.
auto Automático Irrelevante Implícito y por lo tanto redundante para objetos declarados en el ámbito de bloque.
register Automático Irrelevante Relevante solo para objetos con duración de almacenamiento automático. Proporciona una pista de que la variable debe almacenarse en un registro. Una restricción impuesta es que uno no puede usar el operador unario & "dirección de" en dicho objeto, y por lo tanto el objeto no puede tener un alias.
typedef Irrelevante Irrelevante No es un especificador de clase de almacenamiento en la práctica, pero funciona como uno desde un punto de vista sintáctico. La única diferencia es que el identificador declarado es un tipo, en lugar de un objeto.
_Thread_local Hilo Interno externo Introducido en C11, para representar la duración del almacenamiento de hilos . Si se usa en el alcance del bloque, también incluirá extern o static .

Cada objeto tiene una duración de almacenamiento asociada (independientemente del alcance) y la vinculación (relevante solo para las declaraciones en el alcance del archivo), incluso cuando se omiten estas palabras clave.

El ordenamiento de los especificadores de clase de almacenamiento con respecto a los especificadores de tipo de nivel superior ( int , unsigned , short , etc.) y los calificadores de tipo de nivel superior ( const , volatile ) no se aplica, por lo que ambas declaraciones son válidas:

int static const unsigned a = 5; /* bad practice */
static const unsigned int b = 5; /* good practice */

Sin embargo, se considera una buena práctica poner primero los especificadores de clase de almacenamiento, luego los calificadores de cualquier tipo, luego el especificador de tipo ( void , char , int , signed long , unsigned long long , long double ...).

No todos los especificadores de clase de almacenamiento son legales en un determinado ámbito:

register int x; /* legal at block scope, illegal at file scope */
auto int y; /* same */

static int z; /* legal at both file and block scope */
extern int a; /* same */

extern int b = 5; /* legal and redundant at file scope, illegal at block scope */

/* legal because typedef is treated like a storage class specifier syntactically */
int typedef new_type_name;

Duración del almacenamiento

La duración del almacenamiento puede ser estática o automática. Para un objeto declarado, se determina según su alcance y los especificadores de clase de almacenamiento.

Duración del almacenamiento estático

Las variables con duración de almacenamiento estático se mantienen activas durante toda la ejecución del programa y se pueden declarar tanto en el alcance del archivo (con o sin static ) como en el alcance del bloque (poniendo la static explícitamente). Por lo general, son asignados e inicializados por el sistema operativo al inicio del programa y se reclaman cuando finaliza el proceso. En la práctica, los formatos ejecutables tienen secciones dedicadas para dichas variables ( data , bss y rodata ) y estas secciones completas del archivo se asignan a la memoria en ciertos rangos.

Duración de almacenamiento de hilo

C11

Esta duración de almacenamiento se introdujo en C11. Esto no estaba disponible en los estándares C anteriores. Algunos compiladores proporcionan una extensión no estándar con semántica similar. Por ejemplo, gcc admite el especificador __thread que se puede usar en estándares C anteriores que no tenían _Thread_local .

Las variables con duración de almacenamiento de subprocesos se pueden declarar tanto en el alcance del archivo como en el alcance del bloque. Si se declara en el ámbito del bloque, también utilizará un especificador de almacenamiento static o extern . Su duración es la ejecución completa del subproceso en el que se crea. Este es el único especificador de almacenamiento que puede aparecer junto a otro especificador de almacenamiento.

Duración del almacenamiento automático

Las variables con duración de almacenamiento automático solo se pueden declarar en el alcance del bloque (directamente dentro de una función o dentro de un bloque en esa función). Solo se pueden utilizar en el período entre la entrada y la salida de la función o el bloque. Una vez que la variable queda fuera del alcance (ya sea volviendo de la función o dejando el bloque), su almacenamiento se desasigna automáticamente. Cualquier referencia adicional a la misma variable desde los punteros no es válida y conduce a un comportamiento indefinido.

En implementaciones típicas, las variables automáticas se ubican en ciertas compensaciones en el marco de pila de una función o en registros.

Enlace externo e interno

La vinculación solo es relevante para los objetos (funciones y variables) declarados en el alcance del archivo y afecta su visibilidad en diferentes unidades de traducción. Los objetos con enlace externo son visibles en todas las demás unidades de traducción (siempre que se incluya la declaración correspondiente). Los objetos con enlace interno no están expuestos a otras unidades de traducción y solo se pueden usar en la unidad de traducción donde están definidos.

Clases de almacenamiento Ejemplos relacionados