Greetings !!
Je me suis retrouvé très con lorsqu'un de mes élèves m'a demandé pourquoi lorsqu'il utilisait return ça fonctionnait alors que en modifiant sa liste passée par adresse à la fonction ça ne fonctionnait pas.
Je "vois" plus ou moins mais j'ai du mal à formuler.
Voici la fonction qui "fonctionne" lol...
Ici on obtient une liste chaînée contenant "quelque chose" qu'il faut trier.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67 LinkedList* lc_sort(LinkedList *source,int (*fctcompare)(void*,void*)) { LinkedList *tmpList=lc_init(); lc_Datas *tmpPG=NULL; int position=1; if(source==NULL) return NULL; lc_Datas *compareme; lc_Datas *parcours; do { parcours=source->pHead; if(parcours==NULL) break; compareme=lc_get(source,position); if(compareme==NULL) // cas du dernier élément non trié... automatiquement le plus petit { int ItemID=lc_add(parcours->value,tmpList,parcours->dataType,parcours->dataSize); lc_setDisplayByID(tmpList,ItemID,parcours->pDisplay); lc_delete(source,parcours->item_Number); break; } tmpPG=compareme; if(parcours->dataType!=compareme->dataType) break; // on ne compare pas des pommes et des poires (ni C et Python) if(parcours->dataType==uepuserdef && fctcompare==NULL) break; // si il n'y a pas de fonction de comparaison on quitte do { switch(parcours->dataType) { case uepbyte: if(*((char*)parcours->value)>*((char*)tmpPG->value)) tmpPG=parcours; break; case uepshort: if(*((short*)parcours->value)>*((short*)tmpPG->value)) tmpPG=parcours; break; case uepint: if(*((int*)parcours->value)>*((int*)tmpPG->value)) tmpPG=parcours; break; case uepfloat: if(*((float*)parcours->value)>*((float*)tmpPG->value)) tmpPG=parcours; break; case ueplong: if(*((long*)parcours->value)>*((long*)tmpPG->value)) tmpPG=parcours; break; case uepllong: if(*((long long*)parcours->value)>*((long long*)tmpPG->value)) tmpPG=parcours; break; case uepdouble: if(*((double*)parcours->value)>*((double*)tmpPG->value)) tmpPG=parcours; break; case uepldouble: if(*((long double*)parcours->value)>*((long double*)tmpPG->value)) tmpPG=parcours; break; default: if(fctcompare(parcours->value,tmpPG->value)>0) tmpPG=parcours; } parcours=parcours->pNext; }while(parcours!=NULL); // Ici nous avons l'élément le plus grand de la collection de valeurs... lc_Datas *copy=lc_search(source,tmpPG->item_Number); int ItemID=lc_add(copy->value,tmpList,tmpPG->dataType,tmpPG->dataSize); lc_setDisplayByID(tmpList,ItemID,compareme->pDisplay); lc_delete(source,tmpPG->item_Number); tmpPG=NULL; }while(source->NbElem>0); // La liste devrait être triée return tmpList; }
Cette manière de procéder permet dans le code source de faire quelque chose comme ceci:
...et d'obtenir ceci:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6 printf("Entiers: \n"); lc_showList(ll_datas_int); ll_datas_int=lc_sort(ll_datas_int,NULL); printf("Entiers triés: \n"); lc_showList(ll_datas_int);
...ce qui est magnifique !!
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12 Entiers: 35 66 38 24 85 Entiers triés: 85 66 38 35 24
Maintenant, au départ l'étudiant -- avait fait ceci:
...là par contre ça ne fonctionnait pas...
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7 void lc_sort(LinkedList *source,int (*fctcompare)(void*,void*)) { LinkedList *tmpList=lc_init(); ... et tout à la fin avant la fin de la fonction source=tmpList; }
Je dois bien dire que -- pour moi -- ça devrait fonctionner, source est un pointeur vers une structure de type LinkedList et tmpList pointe sur une structure de type LinkedList.
Le passage par adresse, pour moi, permet de modifier le contenu de l'argument (ou paramètre) passé à la fonction... or ici manifestement ce n'est pas le cas, au retour de la fonction, ll_datas_int contient bien une adresse mais
tout le reste de la structure est NULL... du coup je sais pas trop bien expliquer.
Ici source est placé sur la pile donc je supposes que l'adresse est codée sur 64bits, tout comme tmpList on aurait tendance de le dire, mais, lui, il provient du heap... lc_init() cache un calloc() ... je pense que le soucis vient de là.
Lorsque nous faisons return nous "dépilons" donc il devrait y avoir un alignement par rapport aux données pointées par les pointeurs respectifs.
J'ai vraiment du mal à être clair sur ce sujet et je ne parviens pas à expliquer pourquoi, ici, les pointeurs n'ont pas l'air de fonctionner et semblent ne pas permettre de se défaire, notamment, de la "limitation liée aux variables locales aux fonctions".
Partager