Pointeur de structure dans fonction C
Résolu/Fermé
A voir également:
- Pointeur de structure dans fonction C
- Fonction si et - Guide
- Logiciel calcul structure bois gratuit - Télécharger - Architecture & Déco
- Fonction moyenne excel - Guide
- Pointeur souris disparu windows 10 - Guide
- Structure d'un rapport de stage - Guide
3 réponses
mamiemando
Messages postés
33446
Date d'inscription
jeudi 12 mai 2005
Statut
Modérateur
Dernière intervention
20 décembre 2024
7 812
7 déc. 2006 à 00:37
7 déc. 2006 à 00:37
Bon un petit rappel pour commencer.
Rappel sur les fonctions en C
- En C les paramètres de fonction sont des recopies.
- A la fin d'une fonction les variables locales sont effacées.
- Par contre ce qui a pu être alloué dans la fonction n'est pas désalloué si ce n'est pas demandé explicitement.
Rappel sur les pointeurs
Un pointeur sert :
1- à modifier quelque chose qu'on aurait aimé passer en paramètre. Concrètement l'adresse est recopiée, mais pas ce qui est à cette adresse
2- à passer un paramètre plus petit (une adresse est plus rapide à recopier qu'une grosse structure)
3- à ne stocker qu'une fois qu'une donnée si on a besoin dans plusieurs structures.
Les allocations mémoires
En toute rigueur :
- à chaque malloc est associé un free situé dans le même horizon (un horizon est une paire d'accolade)
- parfois ce n'est pas possible donc on crée une sorte de constructeur qui fait l'allocation, et on pense à appeler le destructeur à la fin pour libérer la mémoire.
Les listes chainées
Mieux que les listes, les sets
Concrètement ce n'est pas une structure très rapide car l'insertion et l'accès se font en O(n). Une structure de liste triée serait plus rapide, mais idéalement il faudrait une structure d'arbre pour bénéficier d'une dichotomie. Celà suppose que tu aies une relation d'ordre sur les datas. En C++ ca s'écrit présque immédiatement :
Le set permet définit un ensemble ordonné d'élément insérés de manière unique. L'accès et l'insertion se font en O(log(n)) ce qui est nettement plus rapide...
Bonne chance
Rappel sur les fonctions en C
- En C les paramètres de fonction sont des recopies.
- A la fin d'une fonction les variables locales sont effacées.
- Par contre ce qui a pu être alloué dans la fonction n'est pas désalloué si ce n'est pas demandé explicitement.
Rappel sur les pointeurs
Un pointeur sert :
1- à modifier quelque chose qu'on aurait aimé passer en paramètre. Concrètement l'adresse est recopiée, mais pas ce qui est à cette adresse
2- à passer un paramètre plus petit (une adresse est plus rapide à recopier qu'une grosse structure)
3- à ne stocker qu'une fois qu'une donnée si on a besoin dans plusieurs structures.
Les allocations mémoires
En toute rigueur :
- à chaque malloc est associé un free situé dans le même horizon (un horizon est une paire d'accolade)
- parfois ce n'est pas possible donc on crée une sorte de constructeur qui fait l'allocation, et on pense à appeler le destructeur à la fin pour libérer la mémoire.
Les listes chainées
typedef struct maillon{ struct maillon * suivant; int *data; // dans ton cas une tâche } maillon_t; typedef maillon_t * liste_t; int inserer_tache(liste_t * l,int nouveau){ maillon_t * mcur,mlast; for(mcur = l; mcur; mcur = mcur->suivant){ if( *(mcur->data) == nouveau ) return 0; // deja présent dans la liste } // liste parcourue, on a rien trouvé ! ajout du nouveau maillon mcur->suivant = (maillon_t *)malloc(sizeof(maillon_t)); mlast = mcur->suivant; mlast->suivant = NULL; mlast->data = nouveau; return 1; }
Mieux que les listes, les sets
Concrètement ce n'est pas une structure très rapide car l'insertion et l'accès se font en O(n). Une structure de liste triée serait plus rapide, mais idéalement il faudrait une structure d'arbre pour bénéficier d'une dichotomie. Celà suppose que tu aies une relation d'ordre sur les datas. En C++ ca s'écrit présque immédiatement :
#include <set> // Definition d'une tache struct tache_t{ int x; tache_t(int x0=0):x(x0){} }; // La relation d'ordre bool operator<( const tache_t & t1, const tache_t & t2 ){ return (t1.x < t2.x); } int main(){ std::set<tache_t> taches; // ensemble des taches tache_t t1(1),t2(5),t3(2); taches.insert(t1); taches.insert(t2); taches.insert(t3); return 0; }
Le set permet définit un ensemble ordonné d'élément insérés de manière unique. L'accès et l'insertion se font en O(log(n)) ce qui est nettement plus rapide...
Bonne chance
Char Snipeur
Messages postés
9813
Date d'inscription
vendredi 23 avril 2004
Statut
Contributeur
Dernière intervention
3 octobre 2023
1 298
7 déc. 2006 à 08:54
7 déc. 2006 à 08:54
Salut.
En effet, lors de l'appel d'une fonction avec passage par pointeur, l'adresse est RECOPIER.
exemple :
void sqr(double *x){return*x**x;}
int main {double *y=21;*y=sqr(y);...}
ce qui se passe :
Quand tu declare ta variable y, et que tu l'initialise y prend la valeur \0x001. qui pointe vers une mémoire qui contient 21.
Lors de l'appel de la fonction, tu créé une nouvelle variable 'x' qui prend pour valeur : \0x001.
Si au sein de cette fonction tu modifie x en lui changeant sa valeur :
x=\0x003, et que ensuite tu modifie la case pointé par x, tu ne modifie pas la valeur de y, ni sa valeur pointé.
C'est un peu comme si tu fesait la séquance suivante :
double *y=21;// y vaut \0x001
double* x;x=y;
*x=3;//Ok, tu modifie bien la valeur *y
x=new double;// tu modifie le pointeut x qui vaut \0x002
*x=32;// tu modifie *x, mais pas *y car y vaut toujours \0x001
Voilà, j'espère que ça va t'aider et que j'ai été suffisament clair.
En effet, lors de l'appel d'une fonction avec passage par pointeur, l'adresse est RECOPIER.
exemple :
void sqr(double *x){return*x**x;}
int main {double *y=21;*y=sqr(y);...}
ce qui se passe :
Quand tu declare ta variable y, et que tu l'initialise y prend la valeur \0x001. qui pointe vers une mémoire qui contient 21.
Lors de l'appel de la fonction, tu créé une nouvelle variable 'x' qui prend pour valeur : \0x001.
Si au sein de cette fonction tu modifie x en lui changeant sa valeur :
x=\0x003, et que ensuite tu modifie la case pointé par x, tu ne modifie pas la valeur de y, ni sa valeur pointé.
C'est un peu comme si tu fesait la séquance suivante :
double *y=21;// y vaut \0x001
double* x;x=y;
*x=3;//Ok, tu modifie bien la valeur *y
x=new double;// tu modifie le pointeut x qui vaut \0x002
*x=32;// tu modifie *x, mais pas *y car y vaut toujours \0x001
Voilà, j'espère que ça va t'aider et que j'ai été suffisament clair.