Que fait réellement le compilateur lorsque nous déclarons des variables statiques?

Je veux savoir ce qui se passe sous le capot, comment le compilateur traite les variables statiques. Contrairement à la variable auto, la valeur de la variable statique persiste même après la fin du bloc, mais comment les compilateurs gèrent-ils cela?

Contrairement aux variables locales qui vont sur la stack, les variables statiques sont conservées dans des segments de données spéciaux. Le segment de votre variable statique dépend de si elles sont 0 initialisées ou non. 0 données statiques initialisées vont au format .BSS (Block Started by Symbol), données non initialisées au format .DATA .

Si vous souhaitez en savoir plus sur les différents segments au sein de fichiers exécutables, cette entrée Wikipedia est un bon sharepoint départ. Je recommande également vivement le chapitre 7, intitulé Systèmes informatiques: le sharepoint vue d’un programmeur, par Randal E. Bryant et David R. O’Hallaron.

Je décris ici un scénario particulier. Vous devez tenir compte du fait que les détails varieront d’une architecture à l’autre, d’un système d’exploitation à un autre, et ainsi de suite. Cependant, la disposition générale des fichiers exécutables rest telle que décrite. Des choses passionnantes en effet!

MODIFIER:

L’auteur m’a gentiment demandé de préciser:

quel est le sharepoint diviser la variable initialisée 0 en .bss et non 0 initialisée en .data?

Extrait de la section 7.4 dans Systèmes informatiques: le sharepoint vue d’un programmeur sur la section .BSS :

Cette section n’occupe aucun espace réel dans le fichier d’object; c’est simplement un espace réservé. Les formats de fichier object distinguent les variables initialisées des variables non initialisées pour une utilisation optimisée de l’espace: les variables non initialisées ne doivent occuper aucun espace disque réel dans le fichier object.

Et de Wikipedia :

Généralement, seule la longueur de la section .BSS , mais aucune donnée, est stockée dans le fichier object. Le chargeur de programme alloue et initialise la mémoire pour la section bss lors du chargement du programme.

Pour résumer: c’est un mécanisme pour économiser de la mémoire.

Les compilateurs C typiques produisent une sortie d’assemblage qui crée quatre “sections” de mémoire. L’éditeur de liens / chargeur combine généralement divers éléments étiquetés avec la même section ensemble lorsqu’il charge le programme en mémoire. Les sections les plus communes sont:

“text”: Ceci est le code du programme actuel. Il est considéré comme en lecture seule (l’éditeur de liens / chargeur sur certaines machines peut le placer dans la ROM, par exemple).

“data”: Il s’agit simplement d’une zone allouée de RAM, avec les valeurs initiales copiées à partir du fichier exécutable. Le chargeur va allouer la mémoire, puis copier dans son contenu initial.

“bss”: Identique aux données, mais initialisé à zéro.

“stack”: Alloué simplement par le chargeur pour sa stack de programmes.

Les variables globales et statiques sont placées dans “data” et “bss”, et ont donc une durée de vie de la vie du programme. Cependant, les variables statiques ne placent pas leurs noms dans la table des symboles et ne peuvent donc pas être liées de manière externe comme des globales. La visibilité et la durée de vie des variables sont des concepts totalement séparés: la syntaxe de C confond les deux.

Les variables “auto” sont généralement allouées sur la stack lors de l’exécution du programme (toutefois, si elles sont très volumineuses, elles peuvent être allouées sur le tas). Ils n’existent que dans leur cadre de stack.

static variables static sont des variables globales ayant une scope limitée. @ user3386109

  1. static variables static / globales existent pour la durée de vie du programme.
  2. static / global sont initialisés au démarrage du programme soit:

    A. Si ce n’est pas explicitement initialiser: au bit pattern 0 .
    B. sinon à une valeur explicite comme double x = 1.23;

  3. static scope des variables static est soit limitée à

    A. Si défini en dehors d’une fonction: scope du fichier, seul le code dans le fichier peut “voir” la variable.
    B. Si défini dans une fonction: scope du bloc: seul le code dans le bloc peut “voir” la variable.

  4. Son étendue ne contient qu’une seule instance de la variable static sauf si une scope inférieure en définit une autre portant le même nom. Le compilateur “sait” à quelle même variable nommée accéder en utilisant d’abord la scope la plus proche. Il n’est pas recréé ou réinitialisé, même dans une fonction.

Remarque: avec plusieurs threads, d’autres considérations s’appliquent – non illustrées.

 static int fred = 11; int sally = 21; void foo2(void) { static int fred = 31; int sally = 41; printf("static %d non-static %d\n", fred++, sally++); { printf("static %d non-static %d\n", fred++, sally++); { static int fred = 51; int sally = 61; printf("static %d non-static %d\n", fred++, sally++); } } } int main(void) { printf("static %d non-static %d\n", fred++, sally++); foo2(); printf("static %d non-static %d\n", fred++, sally++); foo2(); return 0; } 

Sortie

 static 11 non-static 21 static 31 non-static 41 static 32 non-static 42 static 51 non-static 61 static 12 non-static 22 static 33 non-static 41 static 34 non-static 42 static 52 non-static 61 

Ce code:

 void function() { static int var = 6; // Make something with this variable var++; } 

est semblable à ceci en interne:

 int only_the_comstackr_knows_this_actual_name = 6; void function() { // Make something with the variable only_the_comstackr_knows_this_actual_name++; } 

En d’autres termes, il s’agit d’une sorte de variable “globale” dont le nom, cependant, n’est en conflit avec aucune autre variable globale.