Allocation statique (Static) et allocation dynamique (Stack&Heap) de variables en langage C
Allocation statique des variables
Adresses absolues déterminées au moment de la compilation et de la liaison.
La taille de la mémoire du programme ne peut plus être modifiée pendant l'exécution du programme.
Bien sûr, vous pouvez modifier le programme et le recompiler, mais c'est moins flexible.
Quelles variables sont incluses ?
Variables globales et locales (mot-clé staic)
Les variables globales et les variables locales modifiées par static peuvent enregistrer la valeur de cette variable dans la fonction jusqu'au prochain appel. Cependant, les variables locales modifiées par static ne sont pas visibles du monde extérieur, uniquement visibles dans cette fonction. La sécurité des données est garantie.
Expliquez avec un exemple
statique.c
#include<stdio.h>
int globle_init=100; //全局初始化变量
static int static_globle_init=100; //static修饰的全局初始化变量
int globle_unit; //全局未初始化变量
void f1(){
static int static_init=100; //static修饰的局部初始化变量
static int static_unit; //static修饰的局部未初始化变量
int local_var=100;// 局部初始化变量
static_init++;
local_var++;
printf("The value of static_unit is %d\n",static_unit);
printf("The value of static_init is %d\n",static_init);
printf("The value of local_var is %d\n",local_var);
printf("================================\n");
}
void f2(){
globle_unit=100;
}
int main(){
f1();
f1();
printf("The value of globle_unit is %d\n",globle_unit);
f2();
printf("The value of globle_unit is %d\n",globle_unit);
return 0;
}
Les résultats sont les suivants:
The value of static_unit is 0
The value of static_init is 101
The value of local_var is 101
================================
The value of static_unit is 0
The value of static_init is 102
The value of local_var is 101
================================
The value of globle_unit is 0
The value of globle_unit is 100
À travers les résultats de l'exécution, on constate que :
- Les variables allouées statiquement sont automatiquement initialisées à 0 si elles ne sont pas initialisées.
- La fonction f1() est appelée deux fois et la valeur de sortie de local_var est 101 à chaque fois. Spécifie que les variables locales non modifiées par static sont créées et détruites chaque fois qu'elles entrent et sortent de la portée.
- Pour la variable locale modifiée par staic, la valeur de static_init est 102 lorsqu'elle est appelée pour la deuxième fois, indiquant que la valeur de son premier appel est conservée à la prochaine fois et ne sera pas détruite.
Le langage d'assemblage correspondant (seule la partie variable allouée statiquement est affichée ici)
先介绍一下两个命令
.comm命令声明未初始化的数据的通用内存区域
.lcomm命令声明未初始化数据的本地通用内存数据
Allocation dynamique des variables
empiler
L'allocation de mémoire dynamique du système
esp stack top low address
ebp stack bottom high address
stack croît dans le sens de l'adresse basse
Expliquez avec un exemple
pile.c
#include<stdio.h>
int add_sum(int a,int b,int c){
int d=0;
int e=1;
d=a+b+c;
return d;
}
int main(){
int i=10;
int j=20;
int k=0;
k=add_sum(i,j,30);
}
Le langage assembleur de la fonction principale correspondante
_main:
LFB7:
pushl %ebp
movl %esp, %ebp
andl $-16, %esp
subl $32, %esp
call ___main
movl $10, 28(%esp)//将数值10(变量i)放在esp28位置
movl $20, 24(%esp)//将数值20(变量j)放在esp24位置
movl $0, 20(%esp)//将数值0(变量k)放在esp20位置
movl $30, 8(%esp)//将数值30(常量)放在esp8位置 这里开始放置参数
movl 24(%esp), %eax //将esp24中的数据放在寄存器eax中
movl %eax, 4(%esp)//将eax寄存器中的值放入esp4位置
movl 28(%esp), %eax //将esp28中的数据放在寄存器eax中
movl %eax, (%esp) //将eax寄存器中的值放入esp0位置
call _add_sum//调用函数
movl %eax, 20(%esp)
leave
ret
LFE7:
Assemblage de la fonction add_sum correspondante
_add_sum:
LFB6:
pushl %ebp
movl %esp, %ebp
subl $16, %esp
movl $0, -4(%ebp) //将数值0(变量d)放在ebp-4位置
movl $1, -8(%ebp)//将数值1(变量e)放在ebp-8位置
movl 12(%ebp), %eax //将ebp12位置的值放入寄存器eax
movl 8(%ebp), %edx //将ebp8位置的值放入寄存器edx
addl %edx, %eax //将两个寄存器中的值相加,结果放入寄存器eax
addl 16(%ebp), %eax //将ebp16中的值与寄存器eax中的值相加,结果放入寄存器eax中
movl %eax, -4(%ebp) //把eax中的值放入寄存器ebp-4(变量d)中
movl -4(%ebp), %eax
leave
ret
chiffre correspondant
Tas
Les programmeurs allouent dynamiquement
à tout moment, à la demande
stdlib.h
Ils sont tous deux déclarés dans le fichier d'en-tête
malloc
void *malloc(size_t size)
Utilisé pour effectuer une allocation de mémoire dynamique,
malloc extrait un morceau de mémoire approprié du pool de mémoire et renvoie un pointeur vers ce morceau de mémoire au programme.
Cette mémoire n'est en aucun cas initialisée à ce moment
Paramètres : le nombre d'octets de mémoire à allouer
malloc alloue une mémoire contiguë
Si l'allocation échoue, il renvoie un pointeur NULL
malloc renvoie un pointeur de type void *, car il peut être converti en n'importe quel autre pointeur de n'importe quel type.
libre
void free(void *pointer)
Le paramètre libre utilisé pour effectuer la libération de la mémoire dynamique est
soit NULL, soit la valeur précédemment renvoyée par malloc, calloc, realloc
calloc
viod *calloc(size_t num_elements,size_t element_size)
Utilisé pour effectuer une allocation mémoire dynamique, la différence est qu'il initialise le pointeur mémoire à 0 avant de le retourner.
Paramètres : le nombre d'éléments requis et le nombre d'octets par élément
si l'allocation échoue, un pointeur NULL est retourné
réaffecter
void realloc(void *ptr,size_t new_size)
Permet de modifier la taille d'une mémoire précédemment allouée
Paramètres : un pointeur mémoire à modifier et le nombre d'octets mémoire à allouer.
Si l'allocation échoue, un pointeur NULL est renvoyé
. Si le premier paramètre est NULL, même effet que la fonction malloc.
Un exemple:
#include<stdio.h>
#include<stdlib.h>
int main(void){
int *myInt=(int*)malloc(sizeof(int));
if(myInt!=NULL){
*myInt=5;
free(myInt);
myInt=NULL;
}
return 0;
}
Pile vs tas
Empiler
Accès rapide
Les variables n'ont pas besoin d'écrire de code pour les libérer dans le programme
L'espace est efficacement géré par le processeur, aucune fragmentation de la mémoire ne se produit,
seules les variables locales
sont limitées par la taille de la pile
Les variables ne peuvent pas être redéfinies en taille
Tas
Les variables sont accessibles globalement
Aucune limite sur la taille de la mémoire
Accès (relativement) plus lent
Aucune garantie d'efficacité de l'espace, une fragmentation de la mémoire peut se produire La mémoire
doit être gérée La
taille des variables peut être redéfinie avec realloc