Storage-class specifiers
Especificar la duración de almacenamiento y vinculación de objetos y funciones:
-
-
auto- duración automática y sin vinculación -
register- duración automática y sin vinculación; no se puede obtener la dirección de esta variable -
static- duración estática y vinculación interna (a menos que esté en ámbito de bloque) -
extern- duración estática y vinculación externa (a menos que ya esté declarada interna)
-
|
(desde C11) |
Contenidos |
Explicación
Los especificadores de clase de almacenamiento aparecen en declaraciones y expresiones de literales compuestos (desde C23) . Como máximo puede usarse un especificador , excepto que _Thread_local (hasta C23) thread_local (desde C23) puede combinarse con static o extern para ajustar el linkage (desde C11) . Los especificadores de clase de almacenamiento determinan dos propiedades independientes de los nombres que declaran: duración de almacenamiento e linkage .
_Alignas
(hasta C23)
alignas
(desde C23)
(desde C11)
, y los arreglos
register
no son convertibles a punteros.
|
5)
_Thread_local
(hasta C23)
thread_local
(desde C23)
indica
duración de almacenamiento de hilo
. No puede utilizarse 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 utiliza en una declaración de ámbito de bloque, debe combinarse con
static
o
extern
para determinar la vinculación.
|
(desde C11) |
Si no se proporciona ningún especificador de clase de almacenamiento, los valores predeterminados son:
- extern para todas las funciones
- extern para objetos en ámbito de archivo
- auto para objetos en ámbito de bloque
Para cualquier estructura o unión declarada con un especificador de clase de almacenamiento, la duración de almacenamiento (pero no la vinculación) se aplica a sus miembros, de forma recursiva.
Las declaraciones de funciones en el ámbito de bloque pueden usar extern o ninguna en absoluto. Las declaraciones de funciones en el ámbito de archivo pueden usar extern o static .
Los parámetros de función no pueden usar ningún especificador de clase de almacenamiento aparte de register . Nótese que static tiene un significado especial en parámetros de función de tipo array.
Duración de almacenamiento
Cada objeto tiene una propiedad llamada storage duration , que limita el lifetime del objeto. Existen cuatro tipos de storage duration en C:
-
- automatic duración de almacenamiento automático. El almacenamiento se asigna cuando se entra en el bloque en el que se declaró el objeto y se desasigna cuando se sale de él por cualquier medio ( goto , return , alcanzando el final). Una excepción son los VLA ; su almacenamiento se asigna cuando se ejecuta la declaración, no al entrar al bloque, y se desasigna cuando la declaración sale del ámbito, no cuando se sale del bloque (desde C99) . Si el bloque se entra recursivamente, se realiza una nueva asignación para cada nivel de recursión. Todos los parámetros de función y objetos de ámbito de bloque no static tienen esta duración de almacenamiento, así como los literales compuestos utilizados en ámbito de bloque (hasta C23)
- static duración de almacenamiento estático. La duración del almacenamiento es toda la ejecución del programa, y el valor almacenado en el objeto se inicializa solo una vez, antes de la función main . Todos los objetos declarados static y todos los objetos con enlace interno o externo que no estén declarados _Thread_local (hasta C23) thread_local (desde C23) (desde C11) tienen esta duración de almacenamiento.
|
(desde C11) |
-
- allocated duración de almacenamiento. El almacenamiento se asigna y desasigna bajo solicitud, utilizando funciones de asignación de memoria dinámica .
Vinculación
La vinculación se refiere a la capacidad de un identificador (variable o función) de ser referenciado en otros ámbitos. Si una variable o función con el mismo identificador se declara en varios ámbitos, pero no puede ser referenciada desde todos ellos, entonces se generan varias instancias de la variable. Se reconocen los siguientes tipos de vinculación:
-
-
sin vinculación
. La variable o función solo puede ser referenciada desde el ámbito en el que se encuentra (ámbito de bloque). Todas las variables de ámbito de bloque que no están declaradas
externtienen esta vinculación, así como todos los parámetros de función y todos los identificadores que no son funciones o variables.
-
sin vinculación
. La variable o función solo puede ser referenciada desde el ámbito en el que se encuentra (ámbito de bloque). Todas las variables de ámbito de bloque que no están declaradas
-
-
internal linkage
. La variable o función puede ser referenciada desde todos los ámbitos en la unidad de traducción actual. Todas las variables de ámbito de archivo declaradas
staticoconstexpr(desde C23) tienen este tipo de vinculación, y todas las funciones de ámbito de archivo declaradasstatic(las declaraciones de funciones estáticas solo están permitidas en el ámbito de archivo).
-
internal linkage
. La variable o función puede ser referenciada desde todos los ámbitos en la unidad de traducción actual. Todas las variables de ámbito de archivo declaradas
-
-
external linkage
. La variable o función puede ser referenciada desde cualquier otra unidad de traducción en todo el programa. Todas las variables de ámbito de archivo que no están declaradas
staticoconstexpr(since C23) tienen este tipo de vinculación, todas las declaraciones de funciones de ámbito de archivo que no están declaradasstatic, todas las declaraciones de funciones de ámbito de bloque, y adicionalmente, todas las variables o funciones declaradasexterntienen este tipo de vinculación a menos que una declaración previa con vinculación interna sea visible en ese punto.
-
external linkage
. La variable o función puede ser referenciada desde cualquier otra unidad de traducción en todo el programa. Todas las variables de ámbito de archivo que no están declaradas
Si el mismo identificador aparece con enlace interno y externo en la misma unidad de traducción, el comportamiento es indefinido. Esto es posible cuando se utilizan definiciones tentativas .
Vinculación y bibliotecas
|
Esta sección está incompleta
Razón: ¿debería ser una entrada separada de nivel superior en c/language bajo Miscellaneous? |
Las declaraciones con enlace externo comúnmente se ponen a disposición en archivos de cabecera para que todas las unidades de traducción que #include el archivo puedan referirse al mismo identificador que está definido en otro lugar.
Cualquier declaración con vinculación interna que aparezca en un archivo de encabezado resulta en un objeto separado y distinto en cada unidad de traducción que incluye ese archivo.
Interfaz de la biblioteca, archivo de cabecera "flib.h":
#ifndef FLIB_H #define FLIB_H void f(void); // declaración de función con enlace externo extern int state; // declaración de variable con enlace externo static const int size = 5; // definición de variable de solo lectura con enlace interno enum { MAX = 10 }; // definición de constante inline int sum (int a, int b) { return a + b; } // definición de función en línea #endif // FLIB_H
Implementación de la biblioteca, archivo fuente "flib.c":
#include "flib.h" static void local_f(int s) {} // definición con enlace interno (solo se usa en este archivo) static int local_state; // definición con enlace interno (solo se usa en este archivo) int state; // definición con enlace externo (usado por main.c) void f(void) { local_f(state); } // definición con enlace externo (usado por main.c)
Código de aplicación, archivo fuente "main.c":
#include "flib.h" int main(void) { int x[MAX] = {size}; // utiliza la constante y la variable de solo lectura state = 7; // modifica state en flib.c f(); // llama a f() en flib.c }
Palabras clave
auto , register , static , extern , _Thread_local thread_local
Notas
|
La palabra clave _Thread_local se utiliza generalmente a través de la macro de conveniencia thread_local , definida en el encabezado <threads.h> . |
(hasta C23) |
Los
typedef
y
constexpr
(desde C23)
especificadores están formalmente listados como especificadores de clase de almacenamiento en la gramática del lenguaje C, pero no especifican almacenamiento.
|
El especificador auto también se utiliza para la inferencia de tipos. |
(desde C23) |
Los nombres en el ámbito de archivo que son const y no son extern tienen enlace externo en C (como valor predeterminado para todas las declaraciones en el ámbito de archivo), pero enlace interno en C++.
Ejemplo
#include <stdio.h> #include <stdlib.h> // static storage duration int A; int main(void) { printf("&A = %p\n", (void*)&A); // automatic storage duration int A = 1; // hides global A printf("&A = %p\n", (void*)&A); // allocated storage duration int* ptr_1 = malloc(sizeof(int)); // start allocated storage duration printf("address of int in allocated memory = %p\n", (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 C23 (ISO/IEC 9899:2024):
-
- 6.2.2 Enlaces de identificadores (p: 35-36)
-
- 6.2.4 Duración de almacenamiento de objetos (p: 36-37)
-
- 6.7.1 Especificadores de clase de almacenamiento (p: 97-100)
- Estándar C17 (ISO/IEC 9899:2018):
-
- 6.2.2 Enlaces de identificadores (p: 29-30)
-
- 6.2.4 Duración de almacenamiento de objetos (p: 30)
-
- 6.7.1 Especificadores de clase de almacenamiento (p: 79)
- Estándar C11 (ISO/IEC 9899:2011):
-
- 6.2.2 Enlaces de identificadores (p: 36-37)
-
- 6.2.4 Duración 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 Enlaces de identificadores (p: 30-31)
-
- 6.2.4 Duración 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 Enlaces de identificadores
-
- 3.1.2.4 Duración de almacenamiento de objetos
-
- 3.5.1 Especificadores de clase de almacenamiento
Véase también
|
Documentación de C++
para
Especificadores de clase de almacenamiento
|