Allocation du memoir en c

Résolu/Fermé
anouar437 Messages postés 8 Date d'inscription mardi 4 novembre 2008 Statut Membre Dernière intervention 3 janvier 2009 - 4 nov. 2008 à 00:52
anouar437 Messages postés 8 Date d'inscription mardi 4 novembre 2008 Statut Membre Dernière intervention 3 janvier 2009 - 4 nov. 2008 à 17:58
salut tt le monde
si on veut faire une allocation dynamique du memoir on utilise la fonction malloc par exemple pour allouer un espace memoir d'un tableau de n entier
p=(int*)malloc(sizeof(n*int)); ici p un pointeur sur int déja déclaré
la question c que j'ai pa compris le roule de (int*)................
on me di ke c pr dire que p est un pointeur sur int mais je pense que c déja déclaré comme un pointeur sur int....
merci d'avance
A voir également:

3 réponses

mamiemando Messages postés 33079 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 23 avril 2024 7 749
4 nov. 2008 à 01:16
Qu'est ce qu'un void * ?

Un malloc alloue une zone mémoire dont la taille est passée en paramètre. Il retourne une adresse générique, c'est à dire un pointeur de type void *.

Lorsqu'on parle d'un pointeur p de type void * cela signifie qu'on ne sait pas de quel type est *p (alors que pour pour un plop_t *, p serait de type plop_t).

Pourquoi typer les pointeurs... puisque ce ne sont jamais que des adresses ?

Or comme tu le sais, les pointeurs ne sont pas toujours simples à utiliser en C et on se mélange rapidement, donc quand on peut typer les pointeurs, on ne s'en prive pas.

Ainsi en cas de mauvaise utilisation, le compilateur peut lever des warnings pour dire qu'on manipule sur une instruction des pointeurs hétérogènes.

Le rôle du (int *) que tu ne comprend pas consiste à caster le pointeur, c'est à dire à écraser ton type (ici void *) par un autre (int *).

En soit tu pourrais ne pas faire le cast, car un malloc ne retourne jamais qu'une adresse. Mais si tu ne fais pas le cast, le compilateur te dira que tu essayes d'affecter un void * dans un int *, et sous-entendra ainsi que soit tu programmes comme un sale, soit que tu t'es craqué.

Conclusion : avec un malloc on fait le cast pour éviter ce genre de warning.

malloc et free

Ceci dit, le fait de caster un pointeur ne te dispense en aucun de libérer la mémoire allouée par le malloc dès que tu n'en a plus besoin avec l'instruction free. Exemple :
#include <stdlib.h>

int main(){
  int *p = (int *)malloc(10*sizeof(int)); // j'alloue une plage de 10 entiers
  unsigned i;
  for(i=0;i<10;++i) p[i] = i;
  free(p); // quand j'ai fini d'utiliser p, je le libère
  return 0;
}


malloc, calloc, realloc

Note qu'il existe d'autres fonctions d'allocation (par exemple calloc) qui comme malloc retournent un pointeur générique (void *) qu'il faut caster.

Bonne chance
0
fiddy Messages postés 11069 Date d'inscription samedi 5 mai 2007 Statut Contributeur Dernière intervention 23 avril 2022 1 835
4 nov. 2008 à 01:26
Salut,
Je ne suis pas vraiment d'accord avec toi. Le cast void* en type* est implicite. Donc pas besoin de le spécifier au compilateur. Le cast entre ces deux derniers était surtout utilisé avec les vieux compilateurs. Mais, aujourd'hui cela est plus dangereux qu'autre chose. Car comme tu dis le cast fera taire le compilateur et enlèvera donc le warning obtenu en oubliant d'inclure stdlib.h. Oups. Pas cool.
Et puis, les compilateurs connaissent les normes maintenant :). Et en plus, cela allège le code. :)
0
mamiemando Messages postés 33079 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 23 avril 2024 7 749 > fiddy Messages postés 11069 Date d'inscription samedi 5 mai 2007 Statut Contributeur Dernière intervention 23 avril 2022
4 nov. 2008 à 01:48
Sauf que je me demande comment tu fais un malloc sans inclure stdlib.h. Et qu'un code qui compile avec des warning ça craint. Je rappelle qu'un warning signifie que le comportement du programme peut varier d'un compilateur à l'autre donc même si ça se passe bien avec un compilateur récent, c'est pas vraiment conseillé de programmer en gardant des warning.

En plus alléger un cast c'est vraiment gagne-petit (un quart de ligne...), alors je ne vois pas trop ce que ça gagne à part donner un code laid. Ça me fait penser aux gens qui ferment pas leur parenthèses en TI-basic en croyant que ça gagne de la place alors que c'est juste illisible :p

En plus, c'est important qu'il comprenne à quoi sert (et quand faire à bon escient) un cast, et le malloc est l'un des cas où il a vraiment du sens ^^
0
fiddy Messages postés 11069 Date d'inscription samedi 5 mai 2007 Statut Contributeur Dernière intervention 23 avril 2022 1 835 > mamiemando Messages postés 33079 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 23 avril 2024
4 nov. 2008 à 10:29
Apparemment je me suis mal exprimé lol. Je la refais.
J'ai jamais dit que ne pas mettre le cast faisait des Warning et je suis comme toi. Un programme doit se compiler sans warning. Sinon, je reformule ce que j'expliquais :
int *p=(int*)malloc(sizeof(int)*n); était obligatoire sur les premiers compilateurs K&R qui ne connaissaient pas bien les normes, donc ça date de longtemps. Maintenant les compilateurs respectent les normes et donc cast impliciement un void * en type*. Donc pas besoin de caster. Et, ne t'inquiète pas, le compilateur ne fera pas apparaître de warning. Jusque là, on pourrait donc penser qu'on a le choix entre caster ou pas.
Sauf que, le seul risque qu'il y a en utilisant malloc (sans compter les problèmes de gestion de la mémoire qui n'est pas un problème à proprement parler du compilateur), c'est l'oubli d'inclure la bibliothèque stdlib. Teste sans l'inclure, tu verras un joli warning, mais pas une erreur (ceci dépend du compilateur).
Or il se trouve que caster le malloc enlève cet avertissement. Voilà pourquoi c'est dangereux de caster le malloc. Caster le malloc empêche au compilateur de prévenir lorsque t'as oublié d'inclure ladite bibliothèque.
Donc, autant écrire : int *p=malloc(sizeof(int)*n). Le compilateur ne fera aucun warning et tout sera propre. Et en plus il t'avertira quant à l'oubli de stdlib.h.
0
mamiemando Messages postés 33079 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 23 avril 2024 7 749 > fiddy Messages postés 11069 Date d'inscription samedi 5 mai 2007 Statut Contributeur Dernière intervention 23 avril 2022
4 nov. 2008 à 12:38
Si tu compiles sans stdlib :
(mando@aldur) (~) $ cat plop.c
int main(){
        int *p = (int *)malloc(sizeof(int));
        free(p);
        return 0;
}
(mando@aldur) (~) $ gcc -W -Wall plop.c
plop.c: In function ‘main’:
plop.c:2: warning: implicit declaration of function ‘malloc’
plop.c:2: warning: incompatible implicit declaration of built-in function ‘malloc’
plop.c:3: warning: implicit declaration of function ‘free’
plop.c:3: warning: incompatible implicit declaration of built-in function ‘free’
Donc là, l'oubli de stdlib se voit. Mais sinon effectivement, si on ne cast pas le malloc il n'y a pas (plus) de warning.
(mando@aldur) (~) $ cat plop.c
#include <stdlib.h>

int main(){
        int *p = malloc(sizeof(int));
        free(p);
        return 0;
}
(mando@aldur) (~) $ gcc -W -Wall plop.c
(mando@aldur) (~) $

Merci pour tes précisions et bonne continuation
0
fiddy Messages postés 11069 Date d'inscription samedi 5 mai 2007 Statut Contributeur Dernière intervention 23 avril 2022 1 835 > mamiemando Messages postés 33079 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 23 avril 2024
4 nov. 2008 à 14:09
Donc là, l'oubli de stdlib se voit.
Oui, car tu utilises un compilateur correct. Mais la version 3.3.6 par exemple ne voyait pas l'oubli de la bibliothèque. Et donc là, cela dépendra du compilateur car non prévu par la norme. Alors que si on ne cast pas, on se retrouve avec un le mauvais prototype de malloc (qui retourne un int au lieu du void*) et là la norme prévoit de te prévenir.
0
Marco la baraque Messages postés 996 Date d'inscription vendredi 9 mai 2008 Statut Contributeur Dernière intervention 5 novembre 2009 328
4 nov. 2008 à 01:18
Bonsoir,
Normalement il vaut mieux utiliser ceci :
int * p = (int*) malloc(n * sizeof(int));

En fait malloc retourne une valeur de type void*. Pour stocker sa valeur de retour dans un int*, il faut faire ce qu'on appelle un 'cast'. C'est-à-dire qu'on va formater la valeur de retour.
Dans ce cas, les pointeurs étant des adresses, même si tu ne castes pas explicitement, tu n'auras pas trop de problème (juste des warnings à la compilation), car quelque soit le type de données, un pointeur est stocké (sur la plupart des architecture) sur 32bits.

Pour te donner un exemple de cast plus pertinent, tu as :
double a = 1.4;
int b = (int) a; //b = 1

Ici, si tu ne mets pas le cast explicite, tu vas avoir une erreur de compilation (un double est stocké sur 64bits, et un int sur 32bits, donc si tu ne le dis pas explicitement tu as une erreur).

C est fortement typé, ce qui signifie qu'il vaut toujours mieux effectuer un cast explicite quand tu as besoin. Par exemple si tu fais :
int a = 2;
short b = a;

Ca risque fort de marcher (même si tu as un warning). C aime bien qu'on déclare et respecte bien les types des données (d'où le cast de void* en int*).

Cordialement,
0
anouar437 Messages postés 8 Date d'inscription mardi 4 novembre 2008 Statut Membre Dernière intervention 3 janvier 2009
4 nov. 2008 à 01:30
merci pr votre aide
j'ai bien compris
0
fiddy Messages postés 11069 Date d'inscription samedi 5 mai 2007 Statut Contributeur Dernière intervention 23 avril 2022 1 835
4 nov. 2008 à 01:33
D'accord pour le double en int. Car il y a perte de précision. Mais le cast entre void* et type* est inutile car implicite.Et cela est même déconseillé. A moins, d'utiliser les tous premiers compilateurs. Mais bon, cas très rare. Voir la remarque 3 pour plus de détails.
Cdlt
0
anouar437 Messages postés 8 Date d'inscription mardi 4 novembre 2008 Statut Membre Dernière intervention 3 janvier 2009
4 nov. 2008 à 16:05
mamiemando, svp j'ai testé ce programme
#include <stdio.h>
#include <stdlib.h>

void main()
{
int* p;
unsigned i;
p=malloc(10*sizeof(int));
for(i=0;i<10;++i)
{
p[i] = i;
printf("%d",p[i]);
}
free(p);

system("PAUSE");

}
avec ou sans (int*) sa marche bien
est ce que c facultatif ou koi ??
0
fiddy Messages postés 11069 Date d'inscription samedi 5 mai 2007 Statut Contributeur Dernière intervention 23 avril 2022 1 835
4 nov. 2008 à 16:26
Relis la conversation, tu comprendras mieux pourquoi c'est facultatif, voir même déconseillé. A moins de vouloir utiliser des compilateurs très anciens.
Cdlt
0
anouar437 Messages postés 8 Date d'inscription mardi 4 novembre 2008 Statut Membre Dernière intervention 3 janvier 2009 > fiddy Messages postés 11069 Date d'inscription samedi 5 mai 2007 Statut Contributeur Dernière intervention 23 avril 2022
4 nov. 2008 à 17:16
fiddy svp ce que j'ai compris c qu'il est préférable de mettre (int*)
une autre chose, j'essayé d'utilider malloc sans appelle à la bebliothèque stdlib.h et sa march juste avec #include <stdio.h>
0
fiddy Messages postés 11069 Date d'inscription samedi 5 mai 2007 Statut Contributeur Dernière intervention 23 avril 2022 1 835 > anouar437 Messages postés 8 Date d'inscription mardi 4 novembre 2008 Statut Membre Dernière intervention 3 janvier 2009
4 nov. 2008 à 17:31
Salut,
Visiblement, t'as pas très bien compris.
J'essaie de faire au plus clair une dernière fois.
Si tu n'obtiens pas de messages d'erreurs ou d'avertissements en utilisant malloc et compagnie sans avoir inclue stdlib.h c'est que tu n'as pas mis de bonnes options (il est préférable d'afficher tous les avertissements), ou alors que ton compilateur ne respecte pas la norme.
Quoiqu'il en soit, lorsque tu utilises malloc, tu dois inclure stdlib.h. Sinon le retour du prototype de malloc est un int au lieu du vrai void*. C'est d'ailleurs comme ça que le compilateur doit s'apercevoir de l'oubli de la bibliothèque.
De plus, les compilateurs respectant la norme savent parfaitement bien que le cast void* en type* est implicite. Donc pas besoin de caster. Le compilateur s'en chargera tout seul.
Si tu cast quand même, il est possible que (cela dépend du compilateur) tu ne reçois pas d'avertissements. Donc à proscrire.

Pour résumer :
Pour utiliser malloc, pas de cast et on inclue stdlib.h. A moins de vouloir que ça compile sur les vieux compilateurs ne respectant pas la norme).
0
anouar437 Messages postés 8 Date d'inscription mardi 4 novembre 2008 Statut Membre Dernière intervention 3 janvier 2009 > fiddy Messages postés 11069 Date d'inscription samedi 5 mai 2007 Statut Contributeur Dernière intervention 23 avril 2022
4 nov. 2008 à 17:58
merci bcp pour votre attention c'est clair mnt
0