Allocation statique (Static) et allocation dynamique (Stack&Heap) de variables en langage C

Allocation statique (Static) et allocation dynamique (Stack&Heap) de variables en langage C

insérez la description de l'image ici

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 ?

insérez la description de l'image ici

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.

insérez la description de l'image ici

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 :

  1. Les variables allouées statiquement sont automatiquement initialisées à 0 si elles ne sont pas initialisées.
  2. 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.
  3. 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命令声明未初始化数据的本地通用内存数据

insérez la description de l'image ici
insérez la description de l'image ici

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
insérez la description de l'image ici

Tas

Les programmeurs allouent dynamiquement
à tout moment, à la demande

stdlib.hIls 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

Répartition de la mémoire programme

insérez la description de l'image ici

Je suppose que tu aimes

Origine blog.csdn.net/weixin_47138646/article/details/121423140
conseillé
Classement