Besoin d'aide sur les pointeurs
Fermé
aladhia
-
19 juin 2005 à 21:04
mamiemando Messages postés 33407 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 29 novembre 2024 - 20 juin 2005 à 00:06
mamiemando Messages postés 33407 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 29 novembre 2024 - 20 juin 2005 à 00:06
A voir également:
- Besoin d'aide sur les pointeurs
- Plus de pointeur sur mon pc - Guide
- [Souris] Pointeurs inversé ? - Forum souris / Touchpad
- 2 pointeurs de souris sur un écran ✓ - Forum souris / Touchpad
- Pavé tactile bloqué : comment réactiver le touchpad - Guide
- Besoin d'aide pour parametrer pointeur satellite HD Line Sf 700 - Forum TNT / Satellite / Réception
2 réponses
bah mettons que tu declare un tableau:
main()
{
char tableau[80];
char *pointeur;
pointeur=&tableau;
fonction(pointeur);
}
le pointeur te permet de sauveagrder l'adresse d'un tableau ou de tout autre structure allouée dynamiquement et de la renvoyer sans la perdre.mettons que tu alloue dynamiquement une structure dans une fonction, en retournant le pointeur :
pointeur=(char*)malloc(80*sizeof(char));
return pointeur;
ainsi tu peux retourner l'adresse de cette structure , car si tu declarer un tableau normal, comme char tableau[80],tu perdrais le tableau alloué à la fin de ta fonction.
main()
{
char tableau[80];
char *pointeur;
pointeur=&tableau;
fonction(pointeur);
}
le pointeur te permet de sauveagrder l'adresse d'un tableau ou de tout autre structure allouée dynamiquement et de la renvoyer sans la perdre.mettons que tu alloue dynamiquement une structure dans une fonction, en retournant le pointeur :
pointeur=(char*)malloc(80*sizeof(char));
return pointeur;
ainsi tu peux retourner l'adresse de cette structure , car si tu declarer un tableau normal, comme char tableau[80],tu perdrais le tableau alloué à la fin de ta fonction.
mamiemando
Messages postés
33407
Date d'inscription
jeudi 12 mai 2005
Statut
Modérateur
Dernière intervention
29 novembre 2024
7 806
20 juin 2005 à 00:06
20 juin 2005 à 00:06
Pour compléter ce qui est dit...
LA THEORIE
Un pointeur c'est une adresse. Comme en informatique le vide n'existe pas, si tu n'initialise pas cette adresse, elle contient une valeur aléatoire qui n'a aucun sens. Il s'agit de l'initialiser.
Or comme tu t'en doutes, on ne peut pas s'allouer de la mémoire n'importe où ! Sinon les autres programmes vont faire la tête. C'est pourquoi en C il y a la fonction malloc (et la petite soeur calloc) qui sert à trover une plage de mémoire libre et à la réserver.
Ainsi, si je reprends l'exemple :
char *pointeur=(char*)malloc(80*sizeof(char));
malloc cherche une zone mémoire de taille égale à 80 caractères. Il retourne la valeur. Mais malloc renvoie une adresse générique (void *), or dans cette exemple on alloue un tableau de caractère (en vue stocker une chaine de caractère ici). Il faut donc caster cette adresse : c'est le rôle du (char*).
Ok donc à ce stade, pointeur contient l'adresse du début de cette plage. On peut donc écrire sur les 80chars qui suivent ils sont reservés. Si ont ne les avait pas alloué on aurait eu le droit à une belle segmentation fault ;) Si d'ailleurs par la suite on sort de cette plage, on aura egalement une segmentation fault.
Cependant, il faudra penser à libérer cette zone mémoire qu'en tu n'en auras plus besoin (genre à la fin de ton programme mais peut-être pourras-tu le faire avant, auquel cas ne t'en prives pas ;o)). Tu le fait grâce à la fonction free :
free(pointeur);
LA PRATIQUE
Mais si c'est pour allouer 80 caractères, pourquoi ne pas directement faire un :
char[80] machaine;
En effet tu peux le faire ;) Comme en plus tu alloues ta variable de manière statique, le compilateur sait exactement ce qu'il aura à désallouer à la fin de la fonction ou tu l'as déclaré.
En fait en fait des malloc car bien souvent on ne connait pas la taille de se qu'on aura à stocker. On alloue la mémoire dynamiquement et ça on ne peut le faire qu'avec des malloc (inutile d'allouer une matrice 10000*10000 si une matrice 5*5 suffit ;o))
De plus allouer matrice[10000][10000] revient allouer 10000*10000 cases d'entiers contigues et c'est pas dit que ça le fasse ;o)
Autre interêts des pointeurs :
- quand tu stockes un pointeur, tu ne stocke qu'une adresse (qq octets) et non une copie de ce qui est pointé.
- tu sis qu'en C modifier un paramètre d'une fonction ne peut pas se faire (car on fait une copie des paramètre lors de l'appel d'une fonction). En gros si modifies un paramètre de fonction, la portée de la modification sera l'appel de cette fonction. Mais si tu passes l'adresse, tu peux modifier ce qui est pointé ;) Je m'explique
void f(int i){
i++; //l'incrémentation de l'entier i ne sera effective que dans f !!
}
void g(int *i){
(*i)++; //l'entier *i n'est pas paramètre de g() (c'est i) donc la modification aura bien lieu
}
Je te laisse jeter un oeil à ce topic ou on aborde le cas des matrices pour t'exercer :
http://www.commentcamarche.net/forum/affich-1612051-%5BC%5D-Pointeur-vers-tableau-Multidimensionnel?CCMSESSID=277ceb595d805053be9ddf5d4d394113
LES POINTEURS DE POINTEURS
Les pointeurs vont te permettre de définir des structures de données (liste chainées, matrices, graphes,....). Un pointeur ne pointe pas nécessairement directement vers un type de base (char/int...) : il peut aussi pointer :
- sur une structure : struct mystruct * pstruct;
- sur un pointeur : int * pint; int ** p_pint;
En effet une matrice n'est qu'en fait un tableau de tableau
En résumé :
dimension 0 : un entier : int
dimension 1 : liste d'entier : int *
dimension 2 : matrice d'entier (ie un tableau de pointeurs de type int *) : int **
...
LA THEORIE
Un pointeur c'est une adresse. Comme en informatique le vide n'existe pas, si tu n'initialise pas cette adresse, elle contient une valeur aléatoire qui n'a aucun sens. Il s'agit de l'initialiser.
Or comme tu t'en doutes, on ne peut pas s'allouer de la mémoire n'importe où ! Sinon les autres programmes vont faire la tête. C'est pourquoi en C il y a la fonction malloc (et la petite soeur calloc) qui sert à trover une plage de mémoire libre et à la réserver.
Ainsi, si je reprends l'exemple :
char *pointeur=(char*)malloc(80*sizeof(char));
malloc cherche une zone mémoire de taille égale à 80 caractères. Il retourne la valeur. Mais malloc renvoie une adresse générique (void *), or dans cette exemple on alloue un tableau de caractère (en vue stocker une chaine de caractère ici). Il faut donc caster cette adresse : c'est le rôle du (char*).
Ok donc à ce stade, pointeur contient l'adresse du début de cette plage. On peut donc écrire sur les 80chars qui suivent ils sont reservés. Si ont ne les avait pas alloué on aurait eu le droit à une belle segmentation fault ;) Si d'ailleurs par la suite on sort de cette plage, on aura egalement une segmentation fault.
Cependant, il faudra penser à libérer cette zone mémoire qu'en tu n'en auras plus besoin (genre à la fin de ton programme mais peut-être pourras-tu le faire avant, auquel cas ne t'en prives pas ;o)). Tu le fait grâce à la fonction free :
free(pointeur);
LA PRATIQUE
Mais si c'est pour allouer 80 caractères, pourquoi ne pas directement faire un :
char[80] machaine;
En effet tu peux le faire ;) Comme en plus tu alloues ta variable de manière statique, le compilateur sait exactement ce qu'il aura à désallouer à la fin de la fonction ou tu l'as déclaré.
En fait en fait des malloc car bien souvent on ne connait pas la taille de se qu'on aura à stocker. On alloue la mémoire dynamiquement et ça on ne peut le faire qu'avec des malloc (inutile d'allouer une matrice 10000*10000 si une matrice 5*5 suffit ;o))
De plus allouer matrice[10000][10000] revient allouer 10000*10000 cases d'entiers contigues et c'est pas dit que ça le fasse ;o)
Autre interêts des pointeurs :
- quand tu stockes un pointeur, tu ne stocke qu'une adresse (qq octets) et non une copie de ce qui est pointé.
- tu sis qu'en C modifier un paramètre d'une fonction ne peut pas se faire (car on fait une copie des paramètre lors de l'appel d'une fonction). En gros si modifies un paramètre de fonction, la portée de la modification sera l'appel de cette fonction. Mais si tu passes l'adresse, tu peux modifier ce qui est pointé ;) Je m'explique
void f(int i){
i++; //l'incrémentation de l'entier i ne sera effective que dans f !!
}
void g(int *i){
(*i)++; //l'entier *i n'est pas paramètre de g() (c'est i) donc la modification aura bien lieu
}
Je te laisse jeter un oeil à ce topic ou on aborde le cas des matrices pour t'exercer :
http://www.commentcamarche.net/forum/affich-1612051-%5BC%5D-Pointeur-vers-tableau-Multidimensionnel?CCMSESSID=277ceb595d805053be9ddf5d4d394113
LES POINTEURS DE POINTEURS
Les pointeurs vont te permettre de définir des structures de données (liste chainées, matrices, graphes,....). Un pointeur ne pointe pas nécessairement directement vers un type de base (char/int...) : il peut aussi pointer :
- sur une structure : struct mystruct * pstruct;
- sur un pointeur : int * pint; int ** p_pint;
En effet une matrice n'est qu'en fait un tableau de tableau
matrice (int**) [ ..... matrice[i]=adresse d'un tableau d'int (int *) .....] | matrice[i] (int*) [............... matrice[i][j]=int ...........]
En résumé :
dimension 0 : un entier : int
dimension 1 : liste d'entier : int *
dimension 2 : matrice d'entier (ie un tableau de pointeurs de type int *) : int **
...