Eh bien, je ne comprends pas quand et pourquoi il est nécessaire d'allouer de la mémoire en utilisant malloc
.
Voici mon code:
#include <stdlib.h>
int main(int argc, const char *argv[]) {
typedef struct {
char *name;
char *sex;
int age;
} student;
//Now I can do two things
student p;
//or
student *ptr = (student *)malloc(sizeof(student));
return 0;
}
Pourquoi est-il nécessaire d'allouer de la mémoire alors que je peux simplement utiliser student p;
?
malloc
est utilisé pour l'allocation dynamique de mémoire. Comme indiqué, il s’agit d’une allocation dynamique, ce qui signifie que vous allouez de la mémoire au moment de l’exécution. Par exemple, lorsque vous ne connaissez pas la quantité de mémoire disponible lors de la compilation.
Un exemple devrait effacer cela. Dites que vous savez qu'il y aura un maximum de 20 étudiants. Ainsi, vous pouvez créer un tableau avec 20 éléments statiques. Votre tableau pourra accueillir un maximum de 20 étudiants. Mais que se passe-t-il si vous ne connaissez pas le nombre d'étudiants? Disons que la première entrée est le nombre d’élèves. Ce pourrait être 10, 20, 50 ou autre chose. Vous allez maintenant entrer n = le nombre d’étudiants au moment de l’exécution et allouer cette quantité de mémoire de manière dynamique en utilisant malloc
.
Ceci n'est qu'un exemple. Il existe de nombreuses situations de ce type dans lesquelles une allocation dynamique est nécessaire.
Consultez la page de manuel malloc (3) .
Vous utilisez malloc
lorsque vous devez allouer des objets qui doivent exister au-delà de la durée d'exécution du bloc actuel (où une copie avec retour serait également coûteuse), ou si vous devez allouer de la mémoire supérieure à la taille de cette pile (ie: un tableau de pile local de 3mb est une idée mauvaise).
Avant que C99 n'introduise les VLA, vous aussi requis pour allouer un tableau de taille dynamique, mais cela est nécessaire pour la création de structures de données dynamiques telles que des arborescences, des listes et des files d'attente, utilisées par de nombreux systèmes. il y a probablement beaucoup d'autres raisons, ce ne sont que quelques-unes.
En développant un peu la structure de l'exemple, considérons ceci:
#include <stdio.h>
int main(int argc, const char *argv[]) {
typedef struct {
char* name;
char* sex;
char* insurace;
int age;
int yearInSchool;
float tuitionDue;
}student;
//Now I can do two things
student p;
//or
student *p = (student *)malloc(sizeof(student));
return 0
}
C a est un langage qui passe implicitement par valeur plutôt que par référence. Dans cet exemple, si nous passions le "p" à une fonction pour effectuer un travail dessus, nous créerions une copie de la structure entière. Cela utilise de la mémoire supplémentaire (le total de l'espace requis par une structure particulière), est plus lent et peut éventuellement ne pas être correctement redimensionné (plus d'informations à ce sujet en une minute). Cependant, en passant * p, nous ne passons pas la structure entière. Nous ne faisons que passer une adresse en mémoire qui fait référence à cette structure. La quantité de données passée est plus petite (taille d'un pointeur), donc l'opération est plus rapide.
Maintenant, sachant cela, imaginez un programme (comme un système d’information étudiant) qui devra créer et gérer un ensemble d’enregistrements dans des milliers, voire des dizaines de milliers. Si vous transmettez toute la structure par valeur, il faudra plus de temps pour traiter un ensemble de données que pour transmettre un pointeur à chaque enregistrement.
malloc = ALLOCATION de mémoire.
Si vous avez utilisé d'autres langages de programmation, vous avez peut-être utilisé le mot-clé "nouveau".
Malloc fait exactement la même chose en C. Il faut un paramètre, quelle taille de mémoire doit être allouée et il renvoie une variable de pointeur qui pointe vers le premier bloc de mémoire
bloc de mémoire entier, que vous avez créé dans la mémoire. Exemple -
int *p = malloc(sizeof(int)*10);
Maintenant, * p désignera le premier bloc du bloc consécutif de 20 entiers réservé sur la mémoire.
Vous pouvez parcourir chaque bloc en utilisant l'opérateur ++ et -. Bonne chance.
Dans cet exemple, cela semble vraiment inutile. Mais maintenant, imaginez que vous utilisez des sockets ou un fichier IO et que vous deviez lire des paquets de longueur variable que vous ne pouvez dissuader que pendant l'exécution. Ou lorsque vous utilisez des sockets et que chaque connexion client nécessite un peu de stockage sur le serveur. Vous pouvez créer un tableau statique, mais cela vous donne une limite client qui sera déterminante lors de la compilation.
Essayons d'aborder cette question en considérant différents aspects
malloc
vous permet d'allouer des espaces mémoire beaucoup plus grands que celui alloué simplement en utilisant student p;
ou int x[n];
. La raison étant malloc
alloue de l'espace sur le tas tandis que l'autre l'alloue sur la pile
Le langage de programmation C gère la mémoire de manière statique, automatique ou dynamique. Les variables de durée statique sont allouées dans la mémoire principale, généralement avec le code exécutable du programme, et persistent pendant toute la durée de vie du programme; Les variables de durée automatique sont allouées sur la pile et vont et viennent à mesure que les fonctions sont appelées et retournent. Pour les variables de durée statique et de durée automatique, la taille de l'allocation doit être constante à la compilation (sauf dans le cas de tableaux automatiques de longueur variable [5]). Si la taille requise n'est pas connue jusqu'au moment de l'exécution (par exemple, si des données de taille arbitraire sont lues par l'utilisateur ou par un fichier sur disque), l'utilisation d'objets de données de taille fixe est inadéquate. ( de Wikipedia )
Normalement, les variables déclarées seraient supprimées/libérées après le bloc dans lequel elles sont déclarées (elles sont déclarées sur la pile). D'autre part, les variables avec de la mémoire allouée à l'aide de malloc
restent jusqu'au moment où elles sont libérées manuellement.
Cela signifie également qu'il vous est impossible de créer une variable/tableau/structure dans une fonction et de renvoyer son adresse (la mémoire sur laquelle il pointe peut éventuellement être libérée). Le compilateur essaie également de vous en avertir en donnant l'avertissement suivant:
Avertissement - adresse de la mémoire de pile associée à la variable locale 'correspond' renvoyée
Pour plus de détails lisez ceci
realloc
)Comme vous l'avez peut-être deviné, ce n'est pas possible normalement.
Au cas où la mémoire ne pourrait pas être allouée: votre programme pourrait s’arrêter normalement, alors que malloc
renverra une NULL
qui peut facilement être récupérée et traitée dans votre programme
Si vous créez une chaîne telle que char *some_memory = "Hello World";
, vous ne pouvez pas faire some_memory[0] = 'h';
car elle est stockée sous forme de chaîne constante et la mémoire dans laquelle elle est stockée est en lecture seule. Si vous utilisez plutôt malloc, vous pourrez en modifier le contenu ultérieurement . Pour plus d'informations cochez cette réponse
Pour plus de détails sur les tableaux de tailles variables, regardez regardez ceci