allocation en C

allocation en C - C - Programmation

Marsh Posté le 15-02-2006 à 16:13:09    

Bonjour,
Je suis un débutant en C et je voudrais poser une question à propos de l'allocation en C.
En fait, je voudrias avoir la différence entre:
 
int tab[100];
 
et  
 
tab = malloc(sizeof(int) * 10);
 
merci d'avance :)

Reply

Marsh Posté le 15-02-2006 à 16:13:09   

Reply

Marsh Posté le 15-02-2006 à 16:17:45    

allocation statique
 
allocation dynamique

Reply

Marsh Posté le 15-02-2006 à 16:22:00    

oui  mais ça quelle effet sur la mémoire? c'est lequel qui est le  plus interessant à faire?

Reply

Marsh Posté le 15-02-2006 à 16:23:47    

si tu connais a l'avance la taille de ton tableau et que cest pas un truc enorme, static est bien
Si tu ne connais pas a l'avance la taille, ou si tu sais que tu veux un machin bien lourd (plus de 5ko je dirais), vise dynamique
 
Si tu veux que ton tableau survive a la fonction dans laquelle il est crée : dynamique
 

Reply

Marsh Posté le 15-02-2006 à 16:31:21    

mais lorsque je fais malloc(100*sizeof(int)) , cela suppose que je fixe la taille de mon tableau. par exemple ici la taille de mon tableau(d'entiers) est 100.
 

Reply

Marsh Posté le 15-02-2006 à 16:32:48    

ouais, mais tu pourrais ecrire
 
malloc( roger * sizeof(int))
 
alors que tu ne peux pas ecrire
 
int toto[roger];

Reply

Marsh Posté le 15-02-2006 à 16:34:25    

chrisbk a écrit :

alors que tu ne peux pas ecrire
 
int toto[roger];


 
En C99, si.  [:dawa]

Reply

Marsh Posté le 15-02-2006 à 16:35:32    

vala, forcement y'en a un qui allait venir faire son expert et foutre la merde [:pingouino]

Reply

Marsh Posté le 15-02-2006 à 16:38:36    

et ca voudrait dire quoi malloc( roger * sizeof(int)) ?
le problème est que je ne comprends pas pourquoi  tu dis que avec malloc, on peut ne peux pas connaitre la taille en avance?
désolé si j'insiste

Reply

Marsh Posté le 15-02-2006 à 16:45:19    

chrisbk a écrit :

vala, forcement y'en a un qui allait venir faire son expert et foutre la merde [:pingouino]


 
[:klem3i1]
(ouais je sais, c'est nase auprès d'un débutant de sortir ce sort de chose  [:petrus75] )
 

mbarekh a écrit :

et ca voudrait dire quoi malloc( roger * sizeof(int)) ?
le problème est que je ne comprends pas pourquoi  tu dis que avec malloc, on peut ne peux pas connaitre la taille en avance?
désolé si j'insiste


 
"roger" est une variable quelconque qui peut être calculée juste avant le malloc(). Tu ne connais pas sa valeur à la compilation, elle ne sera disponible qu'au tout dernier moment de l'exécution.
 
Comme l'a dit chrisbk, l'allocation dynamique sert essentiellement soit dans ce cas-là, soit pour qu'une allocation soit "persistante", c'est-à-dire que la mémoire utilisée à cet effet restera réservée, jusqu'à ce que tu la libères explicitement (avec free() ). Dans le cas d'un tableau statique, dès que tu sors de la fonction, le tableau n'existe plus.

Reply

Marsh Posté le 15-02-2006 à 16:45:19   

Reply

Marsh Posté le 15-02-2006 à 16:50:44    

si j'ai bien compris je peux faire cela:
int roger ;
int tab[];
tab = malloc( roger * sizeof(int));
roger = 10; // la taille du tableau est 10
roger = 50;// la taille devient 50?

Reply

Marsh Posté le 15-02-2006 à 17:09:28    

Euh non, plutot :
 
roger = 10;
int *tab = malloc(roger *sizeof(int));
 
// changement de size
 
free(tab);
roger = 50;
tab = malloc(roger * sizeof(int));
 
l'allocation est dynamique mais la taille allouee de bouge pas seule, il faut explicitement le liberer et reallouer..
Bon y a aussi realloc(), mais on va y a aller doucement..

Reply

Marsh Posté le 15-02-2006 à 17:11:00    

il fait quoi le realloc?

Reply

Marsh Posté le 15-02-2006 à 17:12:28    

mbarekh a écrit :

si j'ai bien compris je peux faire cela:
int roger ;
int tab[];
tab = malloc( roger * sizeof(int));
roger = 10; // la taille du tableau est 10
roger = 50;// la taille devient 50?


 
Non.
A ce stade, je ne saurais trop te conseiller un livre de C, tu te lances trop tôt dans le code sans connaître les principes de base.
 
Mais si tu tiens à un exemple, tu peux utiliser ceci :

Code :
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <time.h>
  4. /* Tire un nombre aleatoire, entre 1 et max */
  5. unsigned tirage(unsigned max)
  6. {
  7.     if ( max == 0 )
  8.         max = RAND_MAX;
  9.    
  10.     return 1+(unsigned)((double)rand()/((double)RAND_MAX+1)*max);
  11. }
  12. int main(void)
  13. {
  14.    unsigned cases;
  15.    int *tableau = NULL;
  16.    /* Initialisation des nombres aléatoires */
  17.    srand(time(NULL));
  18.  
  19.    /* Tirage aléatoire d'un nombre de cases, entre 1 et 20 */
  20.    cases = tirage(20);
  21.    printf("Nombre de cases : %u\n", cases);
  22.    /* Allocation dynamique et remplissage si l'allocation a reussi */
  23.    tableau = malloc( cases * sizeof *tableau );
  24.    if ( tableau != NULL )
  25.    {
  26.        unsigned i;
  27.      
  28.        for( i = 0; i < cases; i++ )
  29.        {
  30.            tableau[i] = tirage(100);
  31.        }
  32.      
  33.        /* Affichage du contenu du tableau a l'ecran */
  34.        for( i = 0; i < cases; i++ )
  35.        {
  36.            printf("Case n°%u = %u\n", i + 1, tableau[i]);
  37.        }
  38.      
  39.        /* Liberation de la memoire occupee */
  40.        free(tableau);
  41.    }
  42.  
  43.    return EXIT_SUCCESS;
  44. }


 
Ce petit programme alloue un tableau dynamique dont le nombre de case est aléatoire.
Il remplit ces cases, puis les lit et les affiche à l'écran. J'espère que ça t'aidera à comprendre le principe de l'allocation dynamique.
Les commentaires devraient t'aider à comprendre ce que fait ce programme.


Message édité par Elmoricq le 15-02-2006 à 17:13:58
Reply

Marsh Posté le 15-02-2006 à 17:16:28    

merci bcp c'est très gentil :)

Reply

Marsh Posté le 15-02-2006 à 19:48:19    

En fait pour essayer de t'éclairer mbarekh, en c on peut arriver au même résultat avec un tableau et avec une allocation dynamique.
 
En fait déjà pour commencer faut pas perdre de l'esprit que le C est un langage compilé, donc que tout ce que tu fais va être transformé en langage machine (c'est ce que l'on appelle la compilation).
 
Et il se trouve que si tu utilises un tableau le code assembleur généré ne sera pas le même que si tu utilises une allocation dynamique avec malloc() ou calloc().
Le code sera différent car le compilateur ne va gérer la mémoire de la même façon dans les deux cas.
 
 
TABLEAU :
 
il s'utilise de la façon suivante :

Code :
  1. #include <stdio.h>
  2. #define NB 20
  3. ...
  4. int tab[NB];
  5. int k;
  6. for(k=0; k<NB; ++k)
  7.    tab[k] = k;
  8. printf("tab[k] = %d", k, tab[k]);


 
Dans ce cas le compilateur réserve un espace en mémoire de NB*sizeof(int), cette taille n'est pas modifiable (cette taille restera la même jusqu'à la fin de la vie du tableau).
Cet espace mémoire sera géré par le compilateur comme un tableau d'où le nom :) :
- un tableau de NB cases pourra être parcouru par un index allant de 0 à NB-1
- chaque case un tableau sera considéré comme une varaible de type int (dans notre exemple).
- sizeof(tab) donnera la taille du tableau en octets (NB*sizeof(int) ici)
 
ALLOCATION DYNAMIQUE :
 

Code :
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #define NB 20
  4. ...
  5. int *tab;
  6. int k;
  7. if( (tab = malloc(NB*sizeof(int)) == NULL )
  8. {
  9.    fprintf(stderr, "Erreur d'allocation memoire !\n" );
  10.    exit(EXIT_FAILURE);
  11. }
  12. for(k=0; k<NB; ++k)
  13.    tab[k] = k;            // ou *(tab+k) = k;
  14. printf("tab[k] = %d", k, tab[k]);     // ou printf("tab[k] = %d", k, *(tab+k));  
  15. free(tab);


 
Dans ce cas malloc() alloue une place en mémoire d'une taille de NB*sizeof(int).
Cette fois ci le compilateur ne considère pas cet espace comme un tableau, donc le comportement va changer.
Il est possible de changer la taille de cet espace mémoire à l'aide de la fonction realloc(), cette fonction renvoyant un pointeur vers le nouvel espace mémoire alloué.
 
- on peut parcourir cet espace mémoire comme un tableau
- sizeof(tab) donnera la taille d'une adresse en mémoire (soit 4 octets sur un PC en général)


Message édité par pj_crepes le 15-02-2006 à 21:01:13
Reply

Marsh Posté le 15-02-2006 à 19:59:26    

Citation :

sizeof(tab) donnera la taille du tableau (NB ici)


 
attention, la taille et non le nombre d'éléments  (pas NB)  
T tab[N] -> sizeof tab == N * sizeof(T)
 

Citation :

Dans ce cas le compilateur alloue une place en mémoire d'une taille de NB*sizeof(int).


c'est malloc qui alloue, le compilateur génère juste le code d'appel de malloc et le reste il s'en fout et c'est important car ca montre bien tout ce qu'il ne peut pas controler
 

Citation :

Cette fois ci le compilateur ne considère pas cet espace comme un tableau, donc le comportement va changer.


oui, tab est un pointeur, ce n'est pas un tableau
 

Citation :

sizeof(tab) donnera la taille d'une adresse en mémoire (soit 4 octets sur un PC en général)


sizeof tab == sizeof(void *) tout simplement puisqu'on lui passe un objet de type pointeur, et si on lui passe un tableau il renvoi bien la taille du tableau, c'est ce qu'on attend de sizeof. le tout c'est d'avoir compris que tableau != pointeur


Message édité par skelter le 15-02-2006 à 19:59:59
Reply

Marsh Posté le 15-02-2006 à 20:55:46    

Désolé pour l'erreur que j'ai faite en effet dans le cas d'un tableau sizeof(tab) donne la taille en octets et non et non NB.
 
Pour ce qui est de la gestion de la mémoire, je suis d'accord avec toi skelter sur le faite que c'est malloc qui alloue.
C'est parce que je me suis mal exprimé.
En fait il est vrai que c'est un point important (le fait que se soit malloc() qui alloue la mémoire) en revanche y a un deuxièdme point important, c'est que le compilateur gère la mémoire.
 
Par exemple dans le cas d'un tableau c'est lui qui fixe l'endroit en mémoire où il va se trouver.
Si l'on déclare une variable "static" elle ne sera pas rangé au même endroit qu'un variable déclérée "auto"; bon après évidemment y a des histoires de visibilitées mais bref passons.
 
Enfin il faut quand même avoir l'espris que la gestion de mémoire (hors allocation dynamique) est une grosse partie du travail d'un compilateur.
 
 
Pour ce qui est du test sur le malloc() Emmanuel D elahaye, c'est vrai que c'est mieux.
Je l'ai pas mis parce que je n'y ait pas pensé en faisant l'exemple.
Mais étant donné qu'on a aucun système de gestion des exceptions en C il est vrai que sa serait dommage de se priver des remontés d'erreur. :)
 
 
:edit:
 
Merci pour vos remarques par rapport à mes erreurs dans mon précédent post, je l'ai modifié.


Message édité par pj_crepes le 15-02-2006 à 21:00:10
Reply

Marsh Posté le 15-02-2006 à 21:43:18    

mbarekh a écrit :

il fait quoi le realloc?


Il te permet d'agrandir un tableau alloué avec "malloc()" tout en conservant les éléments du tableau déjà présents.
 
La syntaxe générale d'allocation/réallocation (on va dire pour un tableau de type "int" ) c'est :


int *tab;
int *tmp;
...
tab=malloc (n * sizeof(int));
if (tab == NULL)
{
      // Gestion du cas où on n'a pas pu allouer
      // En général, on arrête ici la fonction car le reste ne sert plus à rien
}
 
// Donc ici, "tab" a été alloué puisque sinon, on aurait quitté la fonction
...
...
traitement de "tab"
...
...
 
// Ici, on arrive sur un cas où il faut agrandir "tab" (parce que ça sert à rien de le diminuer)
n=f(n);    // f() strictement croissante donc "n" a augmenté de valeur
 
// Réallocation
tmp=realloc(tab, n * sizeof(int));
if (tmp == NULL)
{
      // Gestion du cas où on n'a pas pu réallouer
      // Comme on n'a pas perdu "tab", la gestion peut être assez fine...
}
else
{
     // Puisque "tmp" contient le nouveau "tab" tout en ayant conservé ses valeurs
     // Ne reste plus qu'à remplacer l'ancien par le nouveau
     tab=tmp;
}
...
...
on continue à utiliser "tab" qui a grandi en taille
...
...
 
// Ici on a fini avec "tab"
free(tab),


 
 


---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed