Storage-class specifiers
Spécifiez la durée de stockage et la liaison des objets et fonctions :
-
-
auto- durée automatique et aucune liaison -
register- durée automatique et aucune liaison ; l'adresse de cette variable ne peut pas être prise -
static- durée statique et liaison interne (sauf au niveau bloc) -
extern- durée statique et liaison externe (sauf si déjà déclaré interne)
-
|
(depuis C11) |
Table des matières |
Explication
Les spécificateurs de classe de stockage apparaissent dans les déclarations et les expressions de littéral composé (depuis C23) . Au plus un spécificateur peut être utilisé , sauf que _Thread_local (jusqu'à C23) thread_local (depuis C23) peut être combiné avec static ou extern pour ajuster la liaison (depuis C11) . Les spécificateurs de classe de stockage déterminent deux propriétés indépendantes des noms qu'ils déclarent : la durée de stockage et la liaison .
_Alignas
(jusqu'à C23)
alignas
(depuis C23)
(depuis C11)
, et les tableaux
register
ne sont pas convertibles en pointeurs.
|
5)
_Thread_local
(jusqu'au C23)
thread_local
(depuis C23)
indique la
durée de stockage de thread
. Il ne peut pas être utilisé avec les déclarations de fonctions. S'il est utilisé sur une déclaration d'objet, il doit être présent sur chaque déclaration du même objet. S'il est utilisé sur une déclaration de portée de bloc, il doit être combiné avec soit
static
soit
extern
pour déterminer la liaison.
|
(depuis C11) |
Si aucun spécificateur de classe de stockage n'est fourni, les valeurs par défaut sont :
- extern pour toutes les fonctions
- extern pour les objets au niveau du fichier
- auto pour les objets au niveau du bloc
Pour toute structure ou union déclarée avec un spécificateur de classe de stockage, la durée de stockage (mais pas la liaison) s'applique à leurs membres, de manière récursive.
Les déclarations de fonctions au niveau du bloc peuvent utiliser extern ou rien du tout. Les déclarations de fonctions au niveau du fichier peuvent utiliser extern ou static .
Les paramètres de fonction ne peuvent utiliser aucun spécificateur de classe de stockage autre que register . Notez que static a une signification particulière dans les paramètres de fonction de type tableau.
Durée de stockage
Chaque objet possède une propriété appelée durée de stockage , qui limite la durée de vie de l'objet. Il existe quatre types de durée de stockage en C :
-
- automatic durée de stockage automatique. Le stockage est alloué lorsque le bloc dans lequel l'objet a été déclaré est entré et désalloué lorsqu'il est quitté par n'importe quel moyen ( goto , return , atteignant la fin). Une exception concerne les VLA ; leur stockage est alloué lorsque la déclaration est exécutée, non à l'entrée du bloc, et désalloué lorsque la déclaration sort de la portée, non lorsque le bloc est quitté (depuis C99) . Si le bloc est entré récursivement, une nouvelle allocation est effectuée pour chaque niveau de récursion. Tous les paramètres de fonction et les objets de portée de bloc non static ont cette durée de stockage, ainsi que les littéraux composés utilisés au niveau du bloc (jusqu'à C23)
- static durée de stockage statique. La durée de stockage est l'exécution entière du programme, et la valeur stockée dans l'objet est initialisée une seule fois, avant la fonction main . Tous les objets déclarés static et tous les objets avec liaison interne ou externe qui ne sont pas déclarés _Thread_local (jusqu'à C23) thread_local (depuis C23) (depuis C11) ont cette durée de stockage.
|
(depuis C11) |
-
- allocated durée de stockage. Le stockage est alloué et désalloué sur demande, en utilisant les fonctions d'allocation dynamique de mémoire .
Liaison
La liaison fait référence à la capacité d'un identifiant (variable ou fonction) à être référencé dans d'autres portées. Si une variable ou fonction avec le même identifiant est déclarée dans plusieurs portées, mais ne peut pas être référencée depuis toutes, alors plusieurs instances de la variable sont générées. Les liaisons suivantes sont reconnues :
-
-
aucune liaison
. La variable ou la fonction ne peut être référencée que depuis la portée dans laquelle elle se trouve (portée de bloc). Toutes les variables de portée de bloc qui ne sont pas déclarées
externont cette liaison, ainsi que tous les paramètres de fonction et tous les identifiants qui ne sont pas des fonctions ou des variables.
-
aucune liaison
. La variable ou la fonction ne peut être référencée que depuis la portée dans laquelle elle se trouve (portée de bloc). Toutes les variables de portée de bloc qui ne sont pas déclarées
-
-
liaison interne
. La variable ou fonction peut être référencée depuis toutes les portées dans l'unité de traduction courante. Toutes les variables de portée de fichier déclarées
staticouconstexpr(depuis C23) ont cette liaison, et toutes les fonctions de portée de fichier déclaréesstatic(les déclarations de fonctions statiques sont uniquement autorisées au niveau de la portée de fichier).
-
liaison interne
. La variable ou fonction peut être référencée depuis toutes les portées dans l'unité de traduction courante. Toutes les variables de portée de fichier déclarées
-
-
external linkage
. La variable ou fonction peut être référencée depuis n'importe quelle autre unité de traduction dans l'ensemble du programme. Toutes les variables de portée fichier qui ne sont pas déclarées
staticouconstexpr(since C23) ont cette liaison, toutes les déclarations de fonctions de portée fichier qui ne sont pas déclaréesstatic, toutes les déclarations de fonctions de portée bloc, et, de plus, toutes les variables ou fonctions déclaréesexternont cette liaison, sauf si une déclaration antérieure avec liaison interne est visible à ce point.
-
external linkage
. La variable ou fonction peut être référencée depuis n'importe quelle autre unité de traduction dans l'ensemble du programme. Toutes les variables de portée fichier qui ne sont pas déclarées
Si le même identifiant apparaît avec une liaison interne et externe dans la même unité de traduction, le comportement est indéfini. Ceci est possible lorsque les définitions provisoires sont utilisées.
Liaison et bibliothèques
|
Cette section est incomplète
Motif : cela devrait-il être une entrée distincte de premier niveau dans c/language sous Divers ? |
Les déclarations avec liaison externe sont généralement mises à disposition dans les fichiers d'en-tête afin que toutes les unités de traduction qui #include le fichier puissent faire référence aux mêmes identifiants définis ailleurs.
Toute déclaration avec une liaison interne qui apparaît dans un fichier d'en-tête résulte en un objet séparé et distinct dans chaque unité de traduction qui inclut ce fichier.
Interface de la bibliothèque, fichier d'en-tête "flib.h" :
#ifndef FLIB_H #define FLIB_H void f(void); // déclaration de fonction avec liaison externe extern int state; // déclaration de variable avec liaison externe static const int size = 5; // définition d'une variable en lecture seule avec liaison interne enum { MAX = 10 }; // définition de constante inline int sum (int a, int b) { return a + b; } // définition de fonction inline #endif // FLIB_H
Implémentation de la bibliothèque, fichier source "flib.c" :
#include "flib.h" static void local_f(int s) {} // définition avec liaison interne (utilisée uniquement dans ce fichier) static int local_state; // définition avec liaison interne (utilisée uniquement dans ce fichier) int state; // définition avec liaison externe (utilisée par main.c) void f(void) { local_f(state); } // définition avec liaison externe (utilisée par main.c)
Code d'application, fichier source "main.c" :
#include "flib.h" int main(void) { int x[MAX] = {size}; // utilise la constante et la variable en lecture seule state = 7; // modifie state dans flib.c f(); // appelle f() dans flib.c }
Mots-clés
auto , register , static , extern , _Thread_local thread_local
Notes
|
Le mot-clé _Thread_local est généralement utilisé via la macro de commodité thread_local , définie dans l'en-tête <threads.h> . |
(jusqu'à C23) |
Les
typedef
et
constexpr
(depuis C23)
sont formellement listés comme des spécificateurs de classe de stockage dans la grammaire du langage C, mais ne spécifient pas de stockage.
|
Le spécificateur auto est également utilisé pour l'inférence de type. |
(depuis C23) |
Les noms au niveau de la portée du fichier qui sont const et non extern ont une liaison externe en C (comme valeur par défaut pour toutes les déclarations de portée de fichier), mais une liaison interne en C++.
Exemple
#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 }
Sortie possible :
&A = 0x600ae4 &A = 0x7ffefb064f5c address of int in allocated memory = 0x1f28c30
Références
- Norme C23 (ISO/CEI 9899:2024) :
-
- 6.2.2 Liaisons des identificateurs (p: 35-36)
-
- 6.2.4 Durées de stockage des objets (p: 36-37)
-
- 6.7.1 Spécificateurs de classe de stockage (p: 97-100)
- Norme C17 (ISO/CEI 9899:2018) :
-
- 6.2.2 Liaisons des identificateurs (p : 29-30)
-
- 6.2.4 Durées de stockage des objets (p : 30)
-
- 6.7.1 Spécificateurs de classe de stockage (p : 79)
- Norme C11 (ISO/CEI 9899:2011) :
-
- 6.2.2 Liaisons des identificateurs (p: 36-37)
-
- 6.2.4 Durées de stockage des objets (p: 38-39)
-
- 6.7.1 Spécificateurs de classe de stockage (p: 109-110)
- Norme C99 (ISO/CEI 9899:1999) :
-
- 6.2.2 Liaisons des identificateurs (p : 30-31)
-
- 6.2.4 Durées de stockage des objets (p : 32)
-
- 6.7.1 Spécificateurs de classe de stockage (p : 98-99)
- Norme C89/C90 (ISO/CEI 9899:1990) :
-
- 3.1.2.2 Liaisons des identificateurs
-
- 3.1.2.4 Durées de stockage des objets
-
- 3.5.1 Spécificateurs de classe de stockage
Voir aussi
|
Documentation C++
pour
Spécificateurs de classe de stockage
|