Question:
Où sont stockées les variables statiques?
Swanand
2012-06-18 17:34:13 UTC
view on stackexchange narkive permalink

Supposons que j'utilise un 8051. J'ai compilé un code qui a une variable statique. Où cette variable statique sera-t-elle stockée? En RAM? Dans la pile? Sur le tas ?? En flash? Où?

Aussi, corrigez-moi si je me trompe: les CONST sont stockés dans la ROM. Et les variables globales sont stockées dans Flash. (Et si je n'ai pas Flash?)

J'attends des réponses en ce qui concerne la programmation intégrée. Ce n'est pas comme dans Code Segment ou en .bss, mais où exactement sur mon tableau?

Je m'attends à ce que les variables statiques soient stockées au même endroit que les variables globales. Après tout, c'est la même chose avec une portée différente. (faites-moi savoir si je me trompe)
Six réponses:
Turbo J
2012-06-18 18:04:30 UTC
view on stackexchange narkive permalink

Supposons que j'utilise un 8051.

Ensuite, vous êtes censé connaître la mémoire CODE, DATA, IDATA, XDATA et PDATA - 8051 est une architecture multi Harvard.

Où cette variable statique sera-t-elle stockée?

C'est une bonne question. Cela dépendra des paramètres du compilateur - généralement appelés "modèle de mémoire"; Mais vous pouvez aussi dire explicitement où le compilateur le placera:

  xdata unsigned int i; // entier dans la mémoire XDATA  

Le compilateur / éditeur de liens devrait être capable de créer un fichier Map, qui vous montrera les adresses de vos variables.

CONST sont stockés dans la ROM.

Cela dépend probablement du compilateur et doit être vérifié par rapport au fichier Map. Je me souviens de les baliser explicitement:

  code const char fooStr [] = "Foo"; // constante de chaîne dans le code = mémoire flash  

Et les variables globales sont stockées dans Flash

Vrai et faux. Ils résident dans l'une des mémoires de données du 8051, mais la valeur initiale sera chargée à partir de Flash au moment du démarrage - à moins que la variable ne soit initialisée avec zéro.

0x6d64
2012-06-18 17:58:43 UTC
view on stackexchange narkive permalink

La réponse suivante est basée sur mon expérience en regardant les mapfiles, si je me trompe sur qc. Veuillez me corriger!

Les variables statiques ne sont certainement pas stockées sur le tas, car cela ne concerne que les variables allouées pendant l'exécution (et les variables statiques sont allouées pendant la compilation).

Les variables statiques sont stockées dans la RAM, tout comme vos variables globales. La portée d'une certaine variable n'a d'importance que pour le compilateur, au niveau du code machine, personne ne vous empêche de lire une variable locale en dehors d'une fonction (tant que votre contrôleur n'a pas de fonctionnalités sophistiquées pour protéger les zones de mémoire contre l'accès) .

Et les variables globales sont stockées dans Flash.

Non. Pensez-y: pour écrire un seul bit de mémoire flash, vous devez effacer tout un bloc de données puis réécrire le tout avec les données modifiées. Et ces étapes ne s'exécutent pas en un seul cycle comme le fait un simple stockage dans la RAM. Les variables globales sont stockées dans la RAM, comme mentionné précédemment. Cela résout également votre confusion sur les systèmes sans flash.

Les "variables statiques" connues au moment de la compilation ne sont pas des variables, mais des constantes. Les variables statiques sont affectées et modifiées au moment de l'exécution. La différence avec les autres variables est leur portée et leur durée de vie: elles existent tant que le programme existe.
@stevenvh: Je peux penser à des exemples de variables statiques, qui ne sont certainement pas constantes. Si vous aviez raison, cela ne signifierait-il pas que le mot-clé `const` serait inutile?
Vous avez modifié votre réponse, mais la façon dont elle était formulée, il semblait être connu au moment de la compilation était le critère de base pour l'appeler statique. Vous pouvez parfaitement définir des variables statiques dont la valeur n'est pas connue au moment de la compilation; vous pouvez les déclarer sans affectation.
supercat
2012-06-18 20:35:10 UTC
view on stackexchange narkive permalink

Sur les processeurs où le magasin de code se trouve dans le même espace d'adressage que toutes les autres variables, les compilateurs placeront généralement les variables globales ou statiques qualifiées "const" dans leur propre section de liens, et les éditeurs de liens seront généralement configurés pour placer cette section dans le magasin de codes du système (flash, OTP ou autre). Cela réduira la quantité de RAM requise par le programme, et réduira la quantité de travail que le code de démarrage doit faire.

Sur les processeurs où le magasin de code est dans un espace d'adressage différent (par exemple le PIC ou 8051), certains compilateurs utiliseront un qualificatif const pour signaler qu'ils doivent placer les variables dans le magasin de code et utiliser des instructions différentes pour y accéder, tandis que d'autres ne le feront pas. Ces compilateurs exigeront que seuls les pointeurs avec un qualificatif const puissent être utilisés pour accéder aux variables déclarées const , car sans cette exigence, les compilateurs ne sauraient pas que des instructions spéciales doivent être utilisé pour accéder à ces pointeurs.

Sur les compilateurs 8051 que j'ai vus (Archimède et Keil), il existe des mots clés spécifiques au compilateur 8051 __data, __idata, __code, __bdata, _ pdata et _xdata disponibles pour indiquer ces variables doit être chargé dans un espace d'adressage particulier. Par défaut, les noms peuvent être utilisés avec ou sans traits de soulignement; les versions sans trait de soulignement sont plus pratiques, mais peuvent être désactivées si, par ex. l'un porte un programme qui utilise des identifiants nommés code ou data ). Si un pointeur est déclaré sans appliquer l'un de ces mots-clés à sa cible, le compilateur allouera trois octets: un pour indiquer l'espace mémoire dans lequel se trouve la cible, et deux pour contenir une adresse de 16 bits si nécessaire. Déclarer une variable const sans appliquer également un qualificatif code entraînera le placement de la variable dans l'espace d'adressage RAM par défaut et le chargement de la valeur par défaut au démarrage; une variable déclarée de cette manière peut être passée au code en attendant un pointeur dans l'espace d'adressage par défaut (mais utilisera la RAM). L'ajout d'une déclaration __code (ou code , si activé) entraînera le placement de la variable dans l'espace de code. Il est généralement préférable d'utiliser la déclaration code que non, mais dans certains cas, surtout si l'élément en question est petit, la facilité relative d'accès aux éléments dans la RAM idata peut faire pour la perte de quelques octets de cet espace.

Robert
2012-06-18 18:43:00 UTC
view on stackexchange narkive permalink

Réponse partielle: "Aussi, corrigez-moi si je me trompe: les CONST sont stockés dans la ROM."

Incorrect. Le mot-clé 'const' est une directive pour aider le compilateur. Lorsqu'une variable est déclarée comme 'const', le compilateur sait qu'elle ne peut pas changer, mais il s'agit toujours d'une variable à laquelle un emplacement mémoire est alloué.

Si vous avez besoin / souhaitez la stocker dans la ROM, alors vous devra utiliser un autre mot-clé pour le compilateur qui lui indique le type de mémoire ou l'emplacement à utiliser. Je ne pense pas qu'il existe un mot clé standardisé pour cela. Probablement parce que C a commencé sa vie sur un PC avec tout l'espace de programme et l'espace variable étant de la RAM.

Pour un PIC, vous utiliseriez le mot-clé «rom» pour déclarer la variable.

par exemple "rom int const x = 42; '

Le placement d'une variable _const_ est parfois contrôlé par un mot-clé non standard. Notez qu'il existe souvent un moyen de configurer l'éditeur de liens pour définir où les variables _const_ sont stockées. Ceci, bien sûr, varie avec chaque chaîne d'outils.
old_timer
2016-03-11 21:36:41 UTC
view on stackexchange narkive permalink

Statique implique que la variable est à la fois isolée de ce fichier / fonction / zone de code. L'endroit où elle est définie est à la fois visible uniquement là-bas et lorsqu'elle est utilisée sur des non-globaux transforme essentiellement cette variable en une variable globale du point de vue du stockage. Une variable locale avec une définition statique signifie que je ne veux pas perdre cette valeur d'un appel de cette fonction à un autre, donc elle doit être stockée globalement pour cette fonction, normalement une variable locale est sur la pile afin que la fonction puisse être repositionnée entrant (une nouvelle copie des variables locales pour chaque entrée dans la fonction). Les globaux statiques sont donc globaux de toute façon, les locaux statiques sont locaux mais stockés avec les globaux. Dans ce que l'on appelle souvent .data, mais les chaînes d'outils peuvent avoir des noms différents. Il s'agit essentiellement de la RAM / mémoire (lecture / écriture) où vos autres globaux sont stockés ou où les variables qui sont initialisées une fois définies

  int x = 7;  

sont stockés. Les variables globales ou les locals statiques qui ne sont pas initialisées une fois définies

  int y;  

sont dans ce que l'on appelle souvent .bss. Ceci est un autre morceau de mémoire de lecture / écriture, mais cette mémoire avant de démarrer main () est mise à zéro pour vous de sorte que, par spécification ou par hypothèse, ces variables sont nulles lorsque votre programme démarre.

const est un moyen de dire que je déclare cela comme une variable en lecture seule, je ne prévois pas chaque stockage juste en lisant. Ainsi, le compilateur peut choisir (en fait, c'est le programmeur car il dicte finalement ce que fait l'éditeur de liens, laissant souvent le script de l'éditeur de liens par défaut être utilisé et ne prenant pas en charge ce travail) si cela passe en flash ou en RAM, il peut aller soit en place et travailler très bien.

Pour les microcontrôleurs et autres endroits où vous devez démarrer et démarrer à partir de la mémoire non volatile (flash / rom / etc). Tout d'abord, le programme lui-même doit être stocké dans quelque chose de non volatile. Ensuite, les éléments .data, les éléments que vous avez initialisés dans votre code lors de la définition de la variable, les éléments qui au moment de la compilation peuvent être déterminés. doit également être dans un stockage non volatile, mais ces données sont finalement en lecture / écriture, de sorte que le code d'amorçage qui s'exécute avant l'appel de main () se charge de copier les blocs .data dans la mémoire de lecture / écriture. Le code .bss ou les variables locales globales ou statiques qui ne sont pas initialisées et supposées être nulles lorsque vous démarrez, celles-ci n'ont pas besoin de stockage non volatile, juste l'emplacement et la quantité, et à partir de là, le bootstrap peut mettre à zéro cette lecture / écrire de la mémoire.

Il y a des raisons pour lesquelles nous communiquons en utilisant des termes comme .text, .data, .bss, .rodata, etc. Parce que nous voyons que les outils placent des éléments de notre programme dans ces endroits et ensuite nous peut voir où ces emplacements doivent vivre dans le stockage non volatile, puis pendant l'exécution si cela est différent. .text bien que maladroit, est notre programme, le code machine et d'autres données associées. .data sont des variables de notre programme qui sont initialisées avant de commencer à être non nulles donc elles doivent être stockées dans un stockage non volatile puis déplacées en lecture / écriture avant de les utiliser. .bss sont des variables de notre programme qui sont supposées être nulles lorsque nous démarrons, donc le montant et l'emplacement doivent être stockés en non volatile et le boostrap peut faire la remise à zéro (ou parfois ils sont simplement stockés sous forme de tas de zéros dans le flash / rom également). .rodata est parfois séparé ce sont les consts parfois les consts se trouvent dans .text, .text et .rodata sont considérés comme étant en lecture seule afin qu'ils puissent rester en flash si votre produit peut gérer cela (les flashs plus récents ont des problèmes de lecture-perturbation donc en dehors du flash sur un microcontrôleur, vous ne voulez pas nécessairement faire cela, vous devez faire attention) ou ils peuvent également être copiés sur RAM.

Ensuite, il y a les termes tas et pile, qui souvent après votre programme si nécessaire, .bss et .data consomment une certaine quantité de RAM, souvent à partir des adresses inférieures. puis le reste de ce ram est divisé en tas et pile, parfois sans ligne continue entre eux, les programmes mal conduits peuvent avoir le tas et la pile entrer en collision provoquant un crash. la pile est souvent de haut en bas et le tas est souvent de bas en haut, mais ce ne sont pas des règles strictes et rapides.

Où sont-elles sur votre tableau? eh bien, cela dépend à la fois de la puce et de la carte quant aux options, puis finalement c'est à vous, le programmeur, de décider lorsque vous contrôlez le processus de compilation et de liaison. La plupart des gens obtiennent un exemple ou une chaîne d'outils qui connaît votre système et vous laissez les paramètres par défaut. Mais vous êtes totalement responsable. Pour qu'un microcontrôleur démarre, vous devez avoir un moyen de le faire, généralement une puce flash activée ou désactivée en fonction du mcu, et les éléments non volatils mentionnés ci-dessus doivent être stockés là-bas ou dans un autre endroit non volatile. . De même, vous avez un peu de RAM, vous devez le diviser avec les éléments de lecture / écriture dont vous avez besoin, y compris la pile et le tas si vous êtes assez courageux pour l'utiliser dans un tel système (pas judicieux). Certains processeurs, la pile fait partie de la conception et vous n'avez pas à vous en soucier, d'autres vous le faites. Si vous avez plusieurs de ces choses, non volatiles ou en lecture / écriture, alors vous pouvez choisir où placer les choses.

si vous utilisez une chaîne d'outils de quelqu'un, ou si vous avez accès à d'autres. Il n'y a aucune raison de supposer qu'ils feront exactement la même chose avec votre programme avec leur script d'éditeur de liens par défaut. généralement, les chaînes d'outils fournissent des fichiers cartographiques ou d'autres moyens de voir où ils ont placé les choses pour vous.

est-il certainement possible d'avoir un système basé sur un microcontrôleur sans flash, à chaque écoute d'une souris ou d'un clavier? Certains des produits ainsi que de nombreux autres peuvent fonctionner sans de telles choses. Certains peuvent par exemple avoir dans la logique de la puce pour gérer l'énumération USB, puis le pilote du système d'exploitation pour ce produit contient le micrologiciel, télécharge le micrologiciel sur la RAM sur le périphérique, et démarre le processeur et réénumère peut-être l'usb afin que c'est maintenant une souris ou autre. tout le monde ne le fait pas mais cela se fait parfois. De même, vous pouvez avoir une autre conception où un autre matériel ou une solution télécharge le programme dans la puce / RAM avant de démarrer le processeur, ce qui donne l'impression que ce processeur n'a pas de flash. Mais vous avez toujours les mêmes concepts .text, .data, .bss et le programme que vous exécutez, que ce soit ram seulement, était encore compilé en programme, aucune donnée d'initialisation et des données d'initialisation non nulles et l'éditeur de liens devait savoir où placez ces choses dans le binaire et corrigez le code pour savoir où l'éditeur de liens a placé les variables qu'il doit utiliser.

AlphaGoku
2016-03-11 15:50:38 UTC
view on stackexchange narkive permalink

Bien que votre question soit liée à 8051 et que de nombreuses bonnes réponses aient été suggérées, j'aimerais également inclure une réponse pour les personnes qui arrivent ici en lisant simplement votre question et non les détails. Je voudrais fournir quelques liens pour l'architecture ARM sur la série de microcontrôleurs LPC utilisant Keil IDE. Voici quelques liens importants qui m'ont aidé à comprendre le comportement de l'emplacement des variables:



Ce Q&R a été automatiquement traduit de la langue anglaise.Le contenu original est disponible sur stackexchange, que nous remercions pour la licence cc by-sa 3.0 sous laquelle il est distribué.
Loading...