Quand la mémoire est-elle allouée pendant la compilation?

Quand j’écris

int main() { int j; } 

La mémoire pour ‘j’ est allouée au moment de la compilation, mais quand pendant la compilation? Quelles sont les différentes étapes de la compilation lorsque la mémoire est allouée à une variable? Et si j était global?

Je suppose que vous mélangez les choses.

Le compilateur n’alloue pas de mémoire pour les variables – il génère un code qui alloue de la mémoire pour les variables au moment de l’exécution. Pour les globaux, il sera ajouté au code de démarrage du programme.

En C, main est compilé de la même manière que toutes les autres fonctions: toutes les variables déclarées dans main seront “allouées” sur la stack. Un cadre de stack est la partie de la stack utilisée par un seul appel de fonction. Le cadre contient des emplacements pour toutes les sections locales utilisées dans une fonction. Cette mémoire est considérée comme temporaire car, lorsque la fonction sera retournée, cette image sera extraite de la stack.

Le compilateur C assignera une adresse statique aux variables globales. Cette adresse est considérée comme faisant partie de “l’image” du binary et a donc un emplacement statique en mémoire. Le compilateur C connaît la taille de chaque type et peut donc réserver la quantité d’espace appropriée dans la structure mémoire du binary pour chaque variable globale. Ensuite, tout code qui accède à cette variable référencera simplement cette adresse à la place.

Vous pouvez examiner l’adresse d’une variable avec un code comme ceci:

 #include int i; void foo(int n) { if(n > 2) return; printf("From foo &n = %xd\n", &n); printf("From foo &i = %xd\n", &i); foo(n+1); } int main() { printf("&i = %xd\n", &i); foo(0); return 0; } 

L’exécution de ce code produit une sortie similaire à:

 ./a.out &i = 600934d From foo &n = 38bc4efcd From foo &i = 600934d From foo &n = 38bc4eccd From foo &i = 600934d From foo &n = 38bc4e9cd From foo &i = 600934d 

Il y a deux choses que vous devriez remarquer ici:

  1. L’adresse de i est constante à chaque fois qu’elle est référencée
  2. L’adresse de n (une variable locale de la fonction foo change à chaque appel de foo. En fait, elle diminuera à chaque fois, car la stack croîtra vers le bas.

Pas au moment de la compilation, votre ‘int j’ sera alloué au démarrage de l’application, lorsque l’application entrera dans la scope de main () (en fait, techniquement, elle ne sera pas allouée, la stack étant utilisée), les globaux seront alloués à l’exécution avant d’entrer dans la scope de main ().

La compilation génère le code exécutable pour un programme. La mémoire du programme est allouée lorsque ce code exécutable est exécuté.

Le processus de compilation n’alloue pas la mémoire. Il génère le code qui alloue la mémoire 🙂

Dans ce cas, j serait une variable dite stack et elle serait allouée lorsque l’exécution entrerait dans la fonction main (). Les variables globales et statiques sont allouées sur le tas à la place.

Voici une courte explication: http://www.costech.or.tz/cs231/websites/C%20Programming/www-ee.eng.hawaii.edu/Courses/ee150/Book/chap14/subsection2.1.1.8.html . Je verrai si je peux en trouver un meilleur.

Il appartient au compilateur de placer j. Généralement, les variables locales sont placées sur la stack et, en tant que tel, le compilateur réservera probablement de l’espace sur la stack pour la durée de la fonction principale. Notez que cela diffère de la mémoire variable globale, qui peut recevoir sa propre mémoire.

La mémoire n’est pas allouée au moment de la compilation, mais au moment de l’exécution. Le compilateur vient de générer du code machine qui exécutera votre programme. Les allocations réelles ont lieu à l’exécution. Dans ce cas, la variable n’est pas utilisée et aucun code ne sera émis pour cette variable.

Je pense que vous regardez les étapes de la compilation, plutôt que l’allocation de mémoire de ‘j’. Depuis que je le pense, voici ce qui se passe:

Une fois que vous avez fourni votre code source au compilateur C, la ou les premières étapes sont une parsing lexicale et sémantique dans laquelle la syntaxe et la sémantique du code source sont analysées pour en vérifier leur exactitude. Si une ou plusieurs erreurs ont été détectées, le compilateur en informe et ne continue pas. Si aucune erreur n’a été trouvée, il en résulte la génération d’une représentation intermédiaire du code source, généralement après diverses optimisations. Cette représentation intermédiaire peut être dans un langage natif (natif de l’OS / architecture, comme en C) ou dans un bytecode indépendant de la plateforme (comme Python / Java ..). La fonction du compilateur se termine ici.

L’allocation de mémoire ne se produit que lorsque vous exécutez le code. C’est le temps d’ exécution du programme. Cela ne vient qu’après la phase de compilation, ce que vous ne voudriez probablement pas savoir ici. Si vous voulez, s’il vous plaît faites le moi savoir. Je vais essayer d’append ce que je sais.

HTH.