Structure de stockage de base des données du programme en langage C intégré

1. Cinq partitions de mémoire principales

La mémoire est divisée en cinq zones, à savoir le tas, la pile, la zone de stockage libre, la zone de stockage globale/statique et la zone de stockage constante.

1. Zone de pile (pile) : FIFO est la zone de stockage des variables qui sont allouées par le compilateur en cas de besoin et automatiquement effacées lorsqu'elles ne sont pas nécessaires. Les variables à l'intérieur sont généralement des variables locales, des paramètres de fonction, etc.

2. Zone de tas (heap) : Ces blocs de mémoire alloués par new, leur libération est ignorée par le compilateur et contrôlée par notre programme d'application. Généralement, un new correspond à une suppression. Si le programmeur ne le libère pas, le système d'exploitation le recyclera automatiquement une fois le programme terminé.

3. Zone de stockage libre : ces blocs de mémoire alloués par malloc, etc. C'est très similaire au tas, mais il utilise free pour mettre fin à sa propre vie.

4. Zone de stockage globale/statique : les variables globales et les variables statiques sont allouées au même bloc de mémoire. Dans le langage C précédent, les variables globales étaient divisées en variables initialisées et non initialisées. Il n'existe pas de telle distinction en C++. Elles partagent la même occupation la même zone mémoire.

5. Zone de stockage constante : Il s'agit d'une zone de stockage relativement spéciale, qui stocke des constantes et ne peut pas être modifiée (bien sûr, vous pouvez la modifier par des moyens illégaux, et il existe de nombreuses méthodes)

La mémoire est principalement divisée en segment de code, segment de données et pile. Le segment de code contient le code du programme et appartient à la mémoire morte. Le segment de données stocke les variables globales, les variables statiques, les constantes, etc., le tas stocke les variables de malloc ou new, et d'autres variables sont stockées dans la pile, et l'espace entre les piles est flottant. La mémoire du segment de données ne sera libérée qu'après l'exécution du programme. L'appel de la fonction recherche d'abord l'adresse d'entrée de la fonction, puis calcule les paramètres formels et les variables temporaires de la fonction, alloue de l'espace dans la pile, copie la copie du paramètre réel dans le paramètre formel, puis effectue une opération de pile, et fait apparaître la pile après l'exécution de la fonction. Les constantes de caractère sont généralement placées dans le segment de données et une seule copie de la même constante de caractère sera enregistrée.

Deuxièmement, la zone de stockage du programme en langage C

1. Pour former un programme exécutable (fichier binaire) à partir du code du langage C (fichier texte), il doit passer par trois étapes de compilation-assemblage-liaison. Le processus de compilation génère un assembleur à partir du fichier texte en langage C, le processus d'assemblage forme l'assembleur en un code machine binaire et le processus de liaison combine les fichiers de code machine binaire générés par chaque fichier source en un seul fichier.

2. Une fois le programme écrit en langage C compilé et connecté, un fichier unifié sera formé, composé de plusieurs parties. Plusieurs autres parties sont générées lors de l'exécution du programme, et chaque partie représente une zone de stockage différente :

1) Segment de code (Code ou Texte)

Le segment de code est constitué du code machine exécuté dans le programme. En langage C, les instructions du programme sont exécutées et compilées pour former du code machine. Pendant l'exécution du programme, le compteur de programme de la CPU pointe vers chaque code machine du segment de code et le processeur les exécute séquentiellement.

2) Segment de données en lecture seule (données RO)

Le segment de données en lecture seule correspond à certaines données utilisées par le programme qui ne seront pas modifiées. La manière d'utiliser ces données est similaire à l'opération de table de recherche. Puisque ces variables n'ont pas besoin d'être modifiées, il suffit de les modifier. placé dans la mémoire morte.

3) Le segment de données de lecture et d'écriture (données RW) a été initialisé

Les données initialisées sont des variables qui sont déclarées dans le programme et qui ont une valeur initiale. Ces variables doivent occuper de l'espace mémoire. Lorsque le programme est exécuté, elles doivent être situées dans une zone mémoire lisible et inscriptible et avoir une valeur initiale pour être lues lorsque le programme est en cours d'exécution. Écrivez.

4) Segment de données non initialisé (BBS)

Les données non initialisées sont déclarées dans le programme, mais il n'y a pas de variable initialisée, ces variables n'ont pas besoin d'occuper de l'espace mémoire avant l'exécution du programme.

5) tas

La mémoire tas n'apparaît que lorsque le programme est en cours d'exécution et est généralement allouée et libérée par le programmeur. Dans le cas d'un système d'exploitation, le système d'exploitation peut récupérer de la mémoire après la fin du programme (comme un processus) si le programme ne la libère pas.

6) pile (statck)

La mémoire tas n'apparaît que lorsque le programme est en cours d'exécution.Les variables utilisées à l'intérieur de la fonction, les paramètres de la fonction et la valeur de retour utiliseront l'espace de pile, et l'espace de pile est automatiquement alloué et libéré par le compilateur.

image

3. Le segment de code, le segment de données en lecture seule, le segment de données en lecture-écriture et le segment de données non initialisé appartiennent à la zone statique, tandis que le tas et la pile appartiennent à la zone dynamique. Le segment de code, le segment de données en lecture seule et le segment de données en lecture-écriture seront générés après la connexion, le segment de données non initialisé sera ouvert lors de l'initialisation du programme, et le tas et la pile seront alloués et libérés pendant l'exécution du programme. .

4. Le programme en langage C est divisé en deux états : image et runtime. Dans l'image formée après compilation et liaison, seuls le segment de code (Texte), le segment de données en lecture seule (R0 Data) et le segment de données en lecture-écriture (RW Data) seront inclus. Avant l'exécution du programme, le segment de données non initialisé (BSS) sera généré dynamiquement, et la zone de tas (Heap) et la zone de pile (Stack) seront également générées dynamiquement lors de l'exécution du programme.

1. De manière générale, dans un fichier image statique, chaque partie est appelée une section (Section) et chaque partie au moment de l'exécution est appelée un segment (Segment). S’ils ne sont pas distingués en détail, ils sont collectivement appelés segments.

2. Une fois le langage C compilé et connecté, un segment de code (TEXT), un segment de données en lecture seule (RO Data) et un segment de données en lecture-écriture (RW Data) seront générés. Au moment de l'exécution, en plus des trois zones ci-dessus, il comprend également la zone de segment de données non initialisée (BBS), la zone de tas (heap) et la zone de pile (Stack).

Troisièmement, le segment du programme de langage C

1. Classification des segments

Le code objet généré par chaque programme source contiendra toutes les informations et fonctions que le programme source doit exprimer. La génération de chaque segment dans le code objet est la suivante :

1) Segment de code (Code)

Le segment de code est généré par chaque fonction du programme, et chaque instruction de la fonction sera finalement compilée et assemblée pour générer du code machine binaire.

2) Segment de données en lecture seule (données RO)

Le segment de données en lecture seule est généré par les données utilisées dans le programme. Les caractéristiques de cette partie des données n'ont pas besoin d'être modifiées pendant le fonctionnement, le compilateur placera donc les données dans la partie en lecture seule. Certaines syntaxes du langage C généreront des segments de données en lecture seule.

2. Segment de données en lecture seule (données RO)

Le segment de données en lecture seule (RO Data) est généré par les données utilisées dans le programme. La caractéristique de cette partie des données est qu'elle n'a pas besoin d'être modifiée pendant le fonctionnement, le compilateur mettra donc les données en lecture. seulement une partie. Les conditions suivantes généreront un segment de données en lecture seule.

1) Variables globales en lecture seule

Définir la variable globale const char a[100]="abcdefg" générera une zone de données en lecture seule d'une taille de 100 octets et l'initialisera avec la chaîne "abcdefg". S'il est défini comme const char a[]="abcdefg" et qu'aucune taille n'est spécifiée, un segment de données en lecture seule de 8 octets sera généré en fonction de la longueur de la chaîne "abcdefgh".

2) Variables locales en lecture seule

Par exemple : la variable const char b[100]=”9876543210” définie à l’intérieur de la fonction ; son processus d’initialisation et ses variables globales.

3) Constantes utilisées dans le programme

Par exemple : utilisez printf("informationn") dans le programme, qui contient une constante de chaîne, le compilateur placera automatiquement la constante "information n" dans la zone de données en lecture seule.

Remarque : Dans const char a[100]={"ABCDEFG"}, une zone de données de 100 octets est définie, mais seuls les 8 premiers octets (7 caractères et « 0 » représentant le terminateur) sont initialisés. Dans cet usage, les octets suivants sont initialisés, mais ils ne peuvent pas être écrits dans le programme et sont en réalité inutiles. Par conséquent, dans le segment de données en lecture seule, une initialisation complète est généralement requise.

3. Lire et écrire un segment de données (RW Data)

Le segment de données en lecture-écriture représente une partie de la zone de données qui peut être lue et écrite dans le fichier cible, et ils sont également parfois appelés segments de données initialisés. Cette partie du segment de données et du code, comme le segment de données en lecture seule, appartient à la zone statique du programme, mais elle présente les caractéristiques de l'Association pour la science et la technologie.

1) Les variables globales ont été initialisées

Par exemple : en dehors de la fonction, définissez la variable globale char a[100]="abcdefg"

2) Les variables statiques locales ont été initialisées

Par exemple : définissez static char b[100]="9876543210" dans la fonction. Les données et tableaux définis par static et initialisés dans la fonction seront compilés sous forme de segments de données en lecture et en écriture.

illustrer:

La caractéristique de la zone de données en lecture-écriture est qu'elle doit être initialisée dans le programme. S'il n'y a qu'une définition et aucune valeur initiale, la zone de données en lecture-écriture ne sera pas générée, mais sera définie comme une zone de données non initialisée ( BSS). Si la variable globale (variable définie en dehors de la fonction) est ajoutée avec un modificateur statique et écrite sous la forme de caractère statique a[100], cela signifie qu'elle ne peut être utilisée qu'à l'intérieur du fichier et ne peut pas être utilisée par d'autres fichiers.

4. Segment de données non initialisé (BSS)

Le segment de données non initialisé est souvent appelé BSS (abréviation de Block start by symbol en anglais). Semblable au segment de données de lecture et d’écriture, il appartient également à la zone de données statiques. Mais les données de cette section ne sont pas initialisées. Il ne sera donc identifié que dans le fichier objet, et ne sera pas vraiment appelé segment dans le fichier objet, qui sera généré au moment de l'exécution. Le segment de données non initialisé n'est généré que pendant la phase d'initialisation de l'exécution, sa taille n'affecte donc pas la taille du fichier objet.

4. Dans un programme en langage C, les problèmes auxquels il faut prêter attention lors de l'utilisation de variables :

1. Les variables définies dans le corps de la fonction sont généralement sur la pile et n'ont pas besoin d'être gérées dans le programme, et sont gérées par le compilateur.

2. L'espace mémoire alloué par des fonctions telles que malloc, calloc et realoc pour allouer de la mémoire se trouve sur le tas, et le programme doit s'assurer qu'il est libéré après utilisation, sinon des fuites de mémoire se produiront.

3. Toutes les fonctions définissent des variables globales en dehors du corps, et les variables ajoutées avec le modificateur static sont stockées dans la zone globale (zone statique), qu'elles se trouvent à l'intérieur ou à l'extérieur de la fonction.

4. Les variables définies à l'aide de const seront placées dans la zone de données en lecture seule du programme.

illustrer:

En langage C, des variables statiques peuvent être définies : les variables statiques définies dans le corps d'une fonction ne peuvent être valides que dans le corps de la fonction ; les variables statiques définies dans le corps de toutes les fonctions ne peuvent être valides que dans ce fichier, et ne peuvent pas être utilisé dans d'autres fichiers source ; Pour les variables globales qui ne sont pas modifiées avec static, elles peuvent être utilisées dans d'autres fichiers source. Ces différences relèvent du concept de compilation, c'est-à-dire que si la variable n'est pas utilisée comme requis, le compilateur signalera une erreur. Les variables globales statiques et non statiques seront placées dans le global (statique) du programme.

Quatrièmement, l'utilisation de la section médiane du programme

La zone globale (zone statique) en langage C correspond en réalité aux segments suivants :

Segment de données en lecture seule : données RO

Segment de données en lecture et en écriture : RW Data

Segment de données non initialisé : données BSS

De manière générale, les variables globales directement définies se trouvent dans la zone de données non initialisées. Si la variable est initialisée, elle se trouve dans la zone de données initialisées (RW Data) et le modificateur const sera placé dans la zone en lecture seule (RO Data).

Par exemple:

const char ro[ ]="this is a readonlydata"; //Segment de données en lecture seule, ne peut pas modifier le contenu du tableau ro, ro est stocké dans le segment de données en lecture seule.

char rw1[ ]="ceci est des données globales en lecture-écriture"; //Le segment de données de lecture et d'écriture a été initialisé et le contenu du tableau rw1 peut être modifié. Il devrait s'agir d'une valeur/affectation au lieu de donner l'adresse "ceci est des données globales en lecture-écriture" à rw1, et ne peut pas changer char rw1[ ]= "ceci est des données globales en lecture-écriture"; //Le segment de données de lecture et d'écriture a été initialisé, et les données du tableau rw1 peuvent avoir un contenu modifié. Ce devrait être la valeur/est l'affectation de ne pas donner l'adresse de "ceci est des données de lecture globales" à rw1, et la valeur de "ceci est des données de lecture globales" ne peut pas être modifiée. puisque les constantes littérales sont placées dans le segment de données en lecture seule

char bss_1[100];//segment de données non initialisé

const char *ptrconst = "constant data"; // "constant data" est placé dans le segment de données en lecture seule et la valeur dans ptrconst ne peut pas être modifiée, car il s'agit d'une attribution d'adresse. ptrconst pointe vers l'adresse où les « données constantes » sont stockées, qui est un segment de données en lecture seule. Mais vous pouvez modifier la valeur de l'adresse ptrconst car elle est stockée dans le segment de données de lecture et d'écriture.

Exemple d'explication :

int main( ){
   
   short b;//b放置在栈上,占用2个字节char a[100];//需要在栈上开辟100个字节,a的值是其首地址char s[]=”abcde”;//s在栈上,占用4个字节,“abcde”本身放置在只读数据存储区,占6字节。s是一个地址//常量,不能改变其地址数值,即s++是错误的。char *p1;//p1在栈上,占用4个字节char *p2 ="123456";//"123456"放置在只读数据存储区,占7个字节。p2在栈上,p2指向的内容不能更//改,但是p2的地址值可以改变,即p2++是对的。static char bss_2[100]; //局部未初始化数据段static int c=0 ; //局部(静态)初始化区p1 = (char *)malloc(10*sizeof(char)); //分配的内存区域在堆区strcpy(p1,”xxx”); //”xxx”放置在只读数据存储区,占5个字节free(p1); //使用free释放p1所指向的内存return 0;}

illustrer:

1. Le segment de données en lecture seule doit inclure les données const définies dans le programme (telles que : const char ro[]), ainsi que les données qui doivent être utilisées dans le programme telles que "123456". Pour les définitions de const char ro[] et const char * ptrconst, la mémoire vers laquelle ils pointent est située dans la zone de données en lecture seule et le contenu pointé ne peut pas être modifié. La différence est que le premier ne permet pas de modifier la valeur de ro ​​dans le programme, et le second permet de modifier la valeur de ptrconst lui-même dans le programme. Pour ces derniers, le réécrire sous la forme suivante ne permettra pas de modifier la valeur de ptrconst elle-même dans le programme :

const char * const ptrcconst = « données const » ;

2. Le segment de données de lecture et d'écriture comprend la variable globale initialisée static char rw1[] et la variable statique locale static char rw2[]. La différence entre rw1 et rw2 est de savoir s'il est utilisé dans la fonction ou s'il peut être utilisé dans l'intégralité du fichier lors de la compilation. Pour le premier, la modification statique signifie que la variable rw1 est accessible lors du contrôle d'autres fichiers du programme. S'il y a une modification statique, rw1 ne peut pas être utilisé dans d'autres fichiers sources du langage C. Cet effet concerne la fonctionnalité de lien de compilation. , mais peu importe qu'il y ait de la statique, la variable rw1 sera placée dans le segment de données de lecture et d'écriture. Pour ce dernier rw2, il s'agit d'une variable statique locale, qui est placée dans la zone de données en lecture-écriture ; si elle n'est pas modifiée avec static, sa signification sera complètement modifiée, et ce sera plutôt une variable locale dans l'espace de la pile. d'une variable statique.

3. Segment de données non initialisé, bss_1[100] et bss_2[200] dans le cas 1 représentent un segment de données non initialisé dans le programme. La différence est que la première est une variable globale et peut être utilisée dans tous les fichiers ; la seconde est une variable locale et n'est utilisée qu'à l'intérieur de la fonction. Le segment de données non initialisé ne définit pas la valeur d'initialisation suivante, donc la taille de la zone doit être spécifiée avec une valeur et le compilateur définira la longueur qui doit être augmentée dans le BBS en fonction de la taille.

4. L'espace de pile comprend des variables utilisées en interne dans la fonction telles que short b et char a[100], ainsi que la valeur de la variable p1 dans char *p1.

1) La mémoire pointée par la variable p1 est construite sur l'espace du tas, et l'espace du tas ne peut être utilisé qu'à l'intérieur du programme, mais l'espace du tas (comme la mémoire pointée par p1) peut être transmis à d'autres fonctions comme une valeur de retour pour le traitement.

2) L'espace de la pile est principalement utilisé pour le stockage des trois types de données suivants :

a. Variables dynamiques à l'intérieur de la fonction

B. Les paramètres de la fonction

c. La valeur de retour de la fonction

3) L'utilisation principale de l'espace de pile concerne les variables dynamiques à l'intérieur de la fonction. L'espace variable est ouvert avant le démarrage de la fonction et est automatiquement récupéré par le compilateur après la sortie de la fonction. Regardez un exemple :

int main( ){
   
       char *p = "tiger";    p[1] = 'I';    p++;    printf("%sn",p);}

Invite après la compilation : erreur de segmentation

analyser:

char *p = "tiger" ; Le système a ouvert 4 octets sur la pile pour stocker la valeur de p. "tigre" est stocké dans la zone de stockage en lecture seule, donc le contenu de "tigre" ne peut pas être modifié, *p="tiger" signifie l'attribution d'adresse, par conséquent, p pointe vers la zone de stockage en lecture seule, modifiant ainsi le contenu pointé par p entraînera une erreur de segment. Mais comme p est stocké sur la pile, la valeur de p peut être modifiée, donc p++ est correct.

Cinq, l'utilisation de const

1. Introduction:

const est un mot clé en langage C, qui limite une variable et ne permet pas de la modifier. L'utilisation de const peut améliorer la robustesse du programme dans un certain programme.De plus, lors de la visualisation du code d'autres personnes, une compréhension claire du rôle joué par const est utile pour comprendre les programmes d'autres personnes.

2. variables et constantes const

1) La variable modifiée par const, sa valeur est stockée dans le segment de données en lecture seule et sa valeur ne peut pas être modifiée. appelées variables en lecture seule.

Sa forme est const int a=5 ; ici vous pouvez utiliser a au lieu de 5

2) Constante : elle existe également dans le segment de données en lecture seule et sa valeur ne peut pas être modifiée. Sa forme est "abc",5

3. Pour les variables const et le contenu limité à const, regardons d'abord un exemple :

typedef char* pStr;int main( ){
   
       char string[6] = “tiger”;    const char *p1 = string;    const pStr p2 = string;    p1++;    p2++;    printf(“p1=%snp2=%sn”,p1,p2);}

Une fois le programme compilé, le message d'erreur est

erreur : incrément de la variable en lecture seule 'p2'

1) La forme de base utilisée par const est : const char m ;

//limite m immuable

2) Remplacez m dans la formule 1, const char *pm;

//Limit *pm est immuable, bien sûr pm est variable, donc p1++ a raison.

3) Remplacez char dans la formule 1, const newType m;

// Restreindre m à être immuable, pStr dans la question est un nouveau type, donc p2 dans la question est immuable et p2++ est faux.

4. const et pointeurs

Dans la déclaration de type, const est utilisé pour modifier une constante. Il existe deux manières de l'écrire comme suit :

1) const devant

const int nValue;//nValue是const

const char *pContent;//*pContent est const, pConst est variable

const (char *)pContent;//pContent est const, *pContent est variable

char *const pContent;//pContent est const, *pContent est variable

const char * const pContent;//pContent et *pContent sont tous deux const

2) const est équivalent à l'instruction ci-dessus à l'arrière

int const nValue;// nValue是const

char const *pContent;//*pContent est const, pContent est variable

(char *) constpContent;//pContent est const, *pContent est variable

char* const pContent;// pContent est const, *pContent est variable

char const* const pContent;//pContent et *pContent sont tous deux const

Explication : L'utilisation conjointe de const et de pointeurs est une confusion très courante en langage C. Voici la règle des deux jours :

1) Tracez une ligne le long du signe *, si const est à gauche de *, alors const est utilisé pour modifier la variable pointée par le pointeur, c'est-à-dire que le pointeur pointe vers une constante ; si const est à droite Du côté de *, const consiste à modifier le pointeur lui-même, c'est-à-dire que le pointeur lui-même est constant. Vous pouvez examiner le sens réel de la déclaration ci-dessus selon cette règle, je pense que cela sera clair en un coup d'œil.

2) Pour const (char *) ; parce que char * est un tout, équivalent à un type (tel que char), il s'agit donc d'un pointeur limité pour être const.

六、data、idata、xdata、pdata、code

En termes de types de stockage de données, la série 8051 dispose d'une mémoire de programme sur puce et hors puce, ainsi que d'une mémoire de données sur puce et hors puce. La mémoire de programme sur puce est également divisée en zone d'adressage direct et type d'adressage indirect, correspondant au code, data, xdata, idata et le type pdata défini selon les caractéristiques de la série 51 utilisent des mémoires différentes, ce qui rendra l'efficacité d'exécution du programme différente. Lors de l'écriture d'un programme C51, il est préférable de spécifier le type de stockage de la variable, qui contribuera à améliorer l’efficacité de l’exécution du programme (ce problème sera spécifiquement décrit plus tard). Légèrement différent de ANSI-C, il n'a que les modes SAMLL, COMPACT et LARGE. Différents modes correspondent à différents systèmes matériels réels et auront des résultats de compilation différents.

La différence entre data, idata, xdata et pdata dans la série 51 :

Données : fait référence de manière fixe aux 128 RAM à l'avant 0x00-0x7f, qui peuvent être directement lues et écrites par acc, avec la vitesse la plus rapide et le plus petit code généré.

idata : fait référence de manière fixe aux 256 RAM devant 0x00-0xff, et les 128 premiers sont exactement les mêmes que les 128 de données, simplement parce que la méthode d'accès est différente. idata est accessible d'une manière similaire aux pointeurs en C. L'instruction dans l'assembly est : mox ACC, @Rx. (Ajout sans importance : idata en c fonctionne bien avec l'accès par pointeur)

xdata : RAM étendue externe, fait généralement référence à l'espace externe 0x0000-0xffff, accessible par DPTR.

pdata : les 256 octets inférieurs de RAM étendue externe, lisent et écrivent lorsque l'adresse apparaît sur A0-A7, utilisez movx ACC, @Rx pour lire et écrire. C'est assez particulier, et C51 semble avoir ce BUG, ​​il est donc recommandé de moins l'utiliser. Mais cela a aussi ses avantages : l'usage spécifique est une question intermédiaire, je n'en parlerai donc pas ici.

Quelle est la fonction du code de table de codes de caractères non signés en langage C d'un micro-ordinateur monopuce ?

La fonction du code est d'indiquer au MCU que les données que j'ai définies doivent être placées dans la ROM (zone de stockage du programme), et ne peuvent pas être modifiées après écriture. En fait, cela équivaut à l'adressage MOVX dans l'assembly (il semble être), car il n'y a pas de méthode qui décrit en détail si elle est stockée dans la ROM ou la RAM (registre), donc cette instruction est ajoutée dans le logiciel pour remplacer l'instruction d'assemblage, et les données correspondantes sont stockées dans la RAM.

Le programme peut être simplement divisé en zone de code (programme) et en zone de données (données). La zone de code ne peut pas être modifiée pendant le fonctionnement. La zone de données contient des variables globales et des variables temporaires, qui doivent être modifiées en permanence. Lire les instructions dans la zone de données , et effectuer des calculs sur les données de la zone de données, de sorte que le support sur lequel la zone de code est stockée n'a pas d'importance. Comme les programmes informatiques précédents stockés sur la carte, la zone de code peut également être placée dans la rom ou dans la RAM Il peut également être placé en flash (mais la vitesse d'exécution est beaucoup plus lente, principalement la lecture du flash prend plus de temps que la lecture de la RAM), donc la méthode générale consiste à mettre le programme en flash, puis à le charger dans la RAM pour l'exécuter ; Zone DATA Il n'y a pas le choix, elle doit être placée en RAM, et elle ne peut pas être modifiée en rom.

Comment bdata l’utilise-t-il ?

Si le programme a besoin de 8 variables binaires ou plus, ce ne sera pas pratique si vous souhaitez attribuer des valeurs à 8 variables à la fois (en réfléchissant) et il n'est pas possible de définir un tableau de bits, il n'y a qu'une seule méthode

charbdata MODE ;

sbit MODE_7 = MODE^7 ;

sbit MODE_6 = MODE^6 ;

sbit MODE_5 = MODE^5 ;

sbit MODE_4 = MODE^4 ;

sbit MODE_3 = MODE^3 ;

sbit MODE_2 = MODE^2 ;

sbit MODE_1 = MODE^1 ;

sbit MODE_0 = MODE^0 ;

La variable 8 bits MODE_n est définie

Il s'agit d'une instruction de définition, un type de données spécial de Keilc. Rappelez-vous que ça doit être sbit

Je ne peux pas bit MODE_0 = MODE^0 ;

Si l’instruction d’affectation est écrite ainsi en langage C, elle est considérée comme une opération XOR.

Par rapport à la RAM du microcontrôleur, Flash est un périphérique d'accès externe.Bien que son emplacement structurel soit installé dans le microcontrôleur, en fait, xdata est placé en dehors de la RAM relative, et Flash est relativement en dehors de la RAM.

La variable inta est définie dans la RAM interne, xdatainta est définie dans la RAM externe ou flash, et uchar codea est définie dans flash.

uchar code duma[]={0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f, 0x40, 0x00}; //Sélectionnez le segment de tube numérique de la cathode commune, la valeur à prendre par le port P2.

Si vous définissez uchar aa[5], le contenu de aa[5] est stocké dans la zone de stockage de données (RAM) et la valeur de chaque élément du tableau peut être modifiée pendant l'exécution du projet par le programme. Après la mise hors tension, le contenu dans aa[5] Les données n'ont pas pu être enregistrées.

S'il est défini que le contenu du code uchar bb[5] est stocké dans la zone de stockage du programme (comme flash), la valeur de chaque élément dans bb[5] ne peut être modifiée que lorsque le programme est programmé, et ne peut pas être modifiée. modifié dans le programme en cours d'exécution du projet. Modifiez, et les données dans bb[5] ne disparaîtront pas après la mise hors tension.

7. La différence entre tas et pile en langage C

Le programme en langage C est compilé et connecté pour former un fichier image binaire après compilation et connexion. Il se compose d'une pile, d'un tas et d'un segment de données (composé de trois parties : un segment de données en lecture seule, un segment de données en lecture-écriture initialisé et un segment de données non initialisé. le segment de données est BBS) Et le segment de code, comme le montre la figure suivante :

image

1. Zone de pile (pile) : automatiquement allouée et libérée par le compilateur, stockant les valeurs des paramètres de fonction, les variables locales et d'autres valeurs. Il fonctionne comme une pile dans une structure de données.

2. Zone de tas (heap) : Généralement allouée et libérée par le programmeur, si le programmeur ne la libère pas, cela peut provoquer une fuite de mémoire. Notez que le tas n'est pas le même que la pile dans la structure de données et que sa classe est la même que la liste chaînée.

3. Zone de code de programme : stockez le code binaire du corps de la fonction.

4. Segment de données : se compose de trois parties :

1) Segment de données en lecture seule :

Le segment de données en lecture seule correspond à certaines données utilisées par le programme qui ne seront pas modifiées. La manière d'utiliser ces données est similaire à l'opération de table de recherche. Puisque ces variables n'ont pas besoin d'être modifiées, il suffit de les modifier. placé dans la mémoire morte. Généralement, les variables modifiées par les constantes const et littérales utilisées dans le programme sont généralement stockées dans le segment de données en lecture seule.

2) Le segment de données de lecture et d'écriture initialisé :

Les données initialisées sont une variable déclarée dans le programme et ont une valeur initiale. Ces variables doivent occuper de l'espace mémoire. Lorsque le programme est exécuté, elles doivent être situées dans une zone mémoire lisible et inscriptible, et avoir une valeur initiale pour être lues lorsque le programme est en cours d'exécution. Écrivez. Dans le programme, il s'agit généralement d'une variable globale initialisée, d'une variable locale statique initialisée (variable initialisée statique modifiée)

3) Segment non initialisé (BSS) :

Les données non initialisées sont déclarées dans le programme, mais il n'y a pas de variable initialisée, ces variables n'ont pas besoin d'occuper de l'espace mémoire avant l'exécution du programme. Semblable au segment de données de lecture et d’écriture, il appartient également à la zone de données statiques. Mais les données de cette section ne sont pas initialisées. Le segment de données non initialisé n'est généré que pendant la phase d'initialisation de l'exécution, sa taille n'affecte donc pas la taille du fichier objet. Dans le programme, il existe généralement des variables globales non initialisées et des variables locales statiques non initialisées.

La différence entre tas et pile

1. Comment postuler

(1) Stack (satck) : automatiquement allouée par le système. Par exemple, déclarez une variable locale int b dans la fonction ; le système crée automatiquement un espace pour b dans la pile.

(2) Heap (heap) : le programmeur doit en faire la demande (appeler malloc, realloc, calloc), spécifier la taille et la libérer par le programmeur. Fuite de mémoire facile à produire.

par exemple : charpe ;

p = (char *)malloc(sizeof(char));//Cependant, p lui-même est sur la pile.

2. Limite de taille des candidatures

1) Pile : sous Windows, la pile est une structure de données qui s'étend jusqu'à l'adresse inférieure et constitue une zone de mémoire continue (sa direction de croissance est opposée à celle de la mémoire). La taille de la pile est fixe. Si l'espace demandé dépasse l'espace restant de la pile, un débordement sera demandé.

2) Tas : Le tas est une structure de données étendue à haute adresse (sa direction de croissance est la même que celle de la mémoire) et c'est une zone de mémoire discontinue. En effet, le système utilise une liste chaînée pour stocker les adresses mémoire libres, qui sont naturellement discontinues, et le sens de parcours de la liste chaînée va de l'adresse inférieure à l'adresse haute. La taille du tas est limitée par la mémoire virtuelle disponible sur le système informatique.

3. Réponse du système :

1) Pile : tant que l'espace de la pile est plus grand que l'espace demandé, le système fournira de la mémoire au programme, sinon une exception sera signalée indiquant un débordement de pile.

2) Tas : Tout d'abord, il faut savoir que le système d'exploitation dispose d'une liste chaînée qui enregistre les adresses mémoire libres, mais lorsque le système reçoit une application d'un programme, il parcourra la liste chaînée pour trouver le premier nœud du tas dont L'espace est plus grand que l'espace demandé, puis le nœud Le point est supprimé de la liste libre, et l'espace du nœud est alloué au programme. De plus, pour la plupart des systèmes, la taille de cette allocation sera enregistrée au première adresse dans cet espace mémoire. De cette manière, l'instruction free dans le code Afin de libérer correctement l'espace mémoire. De plus, la taille du nœud de tas trouvé peut ne pas être exactement égale à la taille demandée, et le système remettra automatiquement la partie redondante dans la liste libre.

Explication : Pour le tas, des nouvelles/suppressions fréquentes entraîneront inévitablement une discontinuité de l'espace mémoire, entraînant un grand nombre de fragments et réduisant l'efficacité du programme. Pour les stacks, ce problème n’existe pas.

4. Efficacité des applications

1) La pile est automatiquement allouée par le système, ce qui est rapide. Mais les programmeurs ne peuvent pas contrôler

2) Le tas est la mémoire allouée par malloc, qui est généralement lente et sujette à la fragmentation, mais c'est la plus pratique à utiliser.

5. Stocker le contenu dans le tas et la pile

1) Pile : lorsqu'une fonction est appelée, l'adresse de l'instruction suivante dans la fonction principale qui est d'abord poussée dans la pile, puis les paramètres de la fonction, les paramètres sont poussés dans la pile de droite à gauche, puis les variables locales dans la fonction . Remarque : Les variables statiques ne sont pas placées sur la pile.

Lorsque cet appel de fonction se termine, les variables locales sont d'abord extraites de la pile, puis les paramètres et enfin le pointeur en haut de la pile pointe vers la première adresse stockée, qui est l'instruction suivante dans la fonction principale, et le le programme continue de s’exécuter à partir de ce point.

2) Tas : généralement, un octet est utilisé pour stocker la taille du tas en tête du tas.

6. Efficacité de l’accès

1) Tas : char *s1="hellowtigerjibo" ; il est déterminé lors de la compilation

2) Pile : char s1[]=”hellowtigerjibo” ; est attribué au moment de l'exécution ; l'utilisation d'un tableau est plus rapide que l'utilisation d'un pointeur, et le pointeur doit être transféré avec le registre edx dans l'assembly sous-jacent, pendant que le tableau est lu la pile.

Remplir:

La pile est une structure de données fournie par le système de la machine. L'ordinateur prendra en charge la pile au niveau de la couche inférieure : attribuez un registre spécial pour stocker l'adresse de la pile, et il existe des instructions spéciales pour pousser et faire éclater la pile, qui détermine que l’efficacité de la pile est relativement élevée. Le tas est fourni par la bibliothèque de fonctions C/C++, et son mécanisme est très compliqué. Par exemple, afin d'allouer un bloc de mémoire, la fonction de bibliothèque recherchera dans la mémoire du tas la mémoire disponible S'il n'y a pas assez d'espace (peut-être à cause à une trop grande fragmentation de la mémoire), il est possible d'appeler la fonction système pour augmenter l'espace mémoire du segment de données du programme, afin qu'il y ait une chance d'allouer suffisamment de mémoire, puis d'effectuer un retour. Évidemment, le tas est bien moins efficace que la pile.

7. Mode de distribution :

1) Le tas est alloué dynamiquement, il n’y a pas de tas alloué statiquement.

2) La pile dispose de deux méthodes d'allocation : l'allocation statique et l'allocation dynamique. L'allocation statique est effectuée par le compilateur, comme l'allocation des variables locales. L'allocation dynamique est allouée par la fonction alloca, mais l'allocation dynamique de la pile est différente de celle du tas. Son allocation dynamique est libérée par le compilateur sans implémentation manuelle.

Je suppose que tu aimes

Origine blog.csdn.net/weixin_41114301/article/details/132287404
conseillé
Classement