Et bien cet opérateur permet d'accéder à la valeur contenu dans le bloc mémoire ou le pointeur pointe.
ex :
Dans ce code px pointe sur x (px contient l'adresse de x)
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6 int x = 10; int *px = &x; *px = 20; printf("x : %d ",x);
quand je fait *px = 20 , c'est la valeur de x que je modifie.
Merci pour ces explications.
Voici ce que je retiens sur l'allocation dynamique des tableaux de 1 à n dimensions. Ci-dessous l'exemple pour un tableau 4d mais le principe est le même pour les tableaux de n'importe quelle dimension même si en pratique c'est rare d'aller au delà de 4d (pour mes applications) :
Merci de m'avoir accompagner dans cette épreuve.
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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107 #include <stdio.h> #include <math.h> #include <stdlib.h> void AllocationDynamique_4D(int *****tab4d, int dim1, int dim2, int dim3, int dim4); void AffichageTableau_4D(int ****tableau, int dim1, int dim2, int dim3, int dim4); void RemplirTableau_4D(int ****tableau, int dim1, int dim2, int dim3, int dim4); void LibereTableau_4D(int ****tableau, int dim1, int dim2, int dim3); int main(int argc, char *argv[]) { int i,j,k; int ****tab; int ***tab3d; int **tab2d; int *tab1d; int dimension1; int dimension2; int dimension3; int dimension4; dimension1=1; dimension2=2; dimension3=2; dimension4=2; AllocationDynamique_4D(&tab,dimension1,dimension2,dimension3,dimension4); RemplirTableau_4D(tab,dimension1,dimension2,dimension3,dimension4); AffichageTableau_4D(tab,dimension1,dimension2,dimension3,dimension4); LibereTableau_4D(tab,dimension1,dimension2,dimension3); return EXIT_SUCCESS; } /* Fin du programme principal */ void AllocationDynamique_4D(int *****tab4d, int dim1, int dim2, int dim3, int dim4) { int i, j, k; *tab4d = calloc(dim1, sizeof(int***)); for(i= 0; i < dim1; i++){ (*tab4d)[i]= (int ***)calloc(dim2, sizeof(int**)); for(j= 0; j < dim2; j++){ (*tab4d)[i][j]= (int **)calloc(dim3, sizeof(int*)); for(k= 0; k < dim3; k++){ (*tab4d)[i][j][k]= (int *)calloc(dim4, sizeof(int)); } } } } void AffichageTableau_4D(int ****tableau, int dim1, int dim2, int dim3, int dim4) { int i,j,k,l; for(i=0;i<dim1;i++){ for(j=0;j<dim2;j++){ for(k=0;k<dim3;k++){ for(l=0;l<dim4;l++){ printf("%d\n",tableau[i][j][k][l]); } } } } } void RemplirTableau_4D(int ****tableau, int dim1, int dim2, int dim3, int dim4) { int i,j,k,l; for(i=0;i<dim1;i++){ for(j=0;j<dim2;j++){ for(k=0;k<dim3;k++){ for(l=0;l<dim4;l++){ tableau[i][j][k][l]=4; } } } } } void LibereTableau_4D(int ****tableau, int dim1, int dim2, int dim3) { int i,j,k; for (i=0; i<dim1; i++){ for (j=0; j<dim2; j++){ for (k=0; k<dim3; k++){ free(tableau[i][j][k]); } free(tableau[i][j]); } free(tableau[i]); } free(tableau); }
ta fonction liberetableau tu lui donne pas l'adresse du pointeur mais le pointeur lui meme, ca marche mais tu peux avoir des suprises vaut mieux lui envoyer la l'adresse, donc ajoute une etoile.
et puis c'est mieux de ne pas toucher au pointeur directement dans la fonction, voici ce que j'aurait fait pour allocation:de meme pour la suppression:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4 int ****p = *tab4d; p=malloc(....) .... *tab4d = p;
et un dernier point, avant un free je te conseil de verifier si le pointeur n'est pas NULL sinon tu vas vers un segfault. ceci est d'autant plus vrai que tu ne testes pas si tes allocations ont marchees.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4 int ****p= *tab4d; .....liste des free; .... free(p);
Merci pour tes remarques, je vais les prendre en compte et voir ce que ça change. C'est peut être l'une des causes possibles qui provoque l'arrêt de mon programme avec un message d'allocation impossible, ça arrive très souvent à la même itération (après plusieurs itérations) lorsque je fais tourner le programme sous Windows alors que sous Linux je n'ai pas cette interruption.
Je fais le test dans le code juste après chaque l'allocation pour m'assurer que l'allocation a réussie mais il n'apparait pas dans le bout de code posté, je fais ceci :
et à la libération :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6 // apres allocation du tableau... if(p==NULL){ printf(" Allocation impossible\n"); exit(EXIT_FAILURE); }
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5 if(p!=NULL) { free(p) }
juste une question a tout hasard et pour satisfaire ma curiosite, pourquoi tu as besoin de 4 dimensions?
Alors c'est un tableau qui contient "un maillage" si l'on peut dire. J'ai une cellule d'étude (un cube) en 3D qui contient des particules sphériques. Je maille la cellule pour la découper en plusieurs voxels (cubes plus petites) et le but est de rechercher les potentiels voisins de chaque particules en se limitant par exemple sur les 8 cubes adjacentes et à chaque fois que je trouve une particule qui coupe une partie de ce petit cube, je la comptabilise et à chaque itération je stocke l'identité de la particule voisine ainsi que la position du centre du petit cube concerné. Le tableau est de la forme :
Actuellement, la déclaration du tableau se fait de la manière suivante :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2 tableau[X][Y][Z][NC]
C'est donc un tableau statique. Le code tourne sans problème mais on est très vite limité par la taille du système.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12 // définition de la taille du système #define X 20 // longueur max suivant x #define Y 20 // longueur max suivant y #define Z 20 // longueur max suivant z #define MAXC 10 // Nombre maxi de voisins tableau[X][Y][Z][MAXC] // dans X on stocke la position en x du cube i // dans Y la position en y du cube i // dans Z la position en z du cube i // dans MAXC l'identité de la particule voisinne,variable...
A chaque fois qu'on veut changer la taille du système il faut modifier la source et plusieurs tableaux de dimensions inférieures sont dimensionnés via X,Y,Z définies plus haut, cette taille du système varie donc... L'idéale serait que l'utilisateur entre via un fichier paramètre, la taille de son système et j'aimerai donc aller progressivement vers une allocation dynamique lorsque la taille des tableaux n'est pas explicitement connue.
J'espère que je t'ai donné une vision de ce que je fais... Je dois absolument adapter la dimension de ce grand tableau en fonction de l'application visée.
Alors sans doute que dans ce cas tu aurais intérêt à utiliser plutôt un tableau à 1 dimension et calculer toi-même les indices et agir par pointeurs..
Faire référence à tab[i][j][k][l] va demander pour chaque élément 4 multiplications et 4 additions.
Si de plus tu as des lignes de calcul et des boucles faisant intervenir au moins 2 éléments du tableau, tu vas descendre les performances d'un facteur énorme...
Il serait sans doute judicieux dans ce cas d'avoir un seul tableau 1D, et de calculer au besoin l'indice..
Si on réfère à 1 seul éléménet, on aura le même temps de calcul. Si par contre on a plusieurs références sur lamême ligne, ou une boucle, on gagnera beaucoup un facteur 6 à chaque référence[)
Par exemple en 2D un tableau tab[dimy][dimx] peut s'écrire de manière équivalente tab[dimx*dimy].
On pourra donc s'y référer, pour un point i,j, avec la première méthode en faisant tab[i][j], avec la seconde tab[i*dimx+j].
Mais par exemple pour se référer au point (i,j+1), avec lapremière méthode ce sera tab[i][j+1], avec la seconde méthode tab[i*dimx+j+1]. Sauf qu'avec cette seconde méthode, si on a stocké un pointeur p = &(tab[i*dimx+j]), on pourra passer au deuxième élément en faisant simplement p++ (soit une addition au lieu de 2 addtions et d'une multiplication, et même 3 additions et 2 multiplications, si on considère ce que fait le compilateur ; 2 additions et une multiplication pour calculer i*dimx+j+1, plus une multiplication et une addiition pour ajouter la taille des N éléments à l'adresse de départ du tableau)
Dans ce cas-là on a donc remplacé 3 additions et 2 multiplications par une seule addition, soit 1/5 des opérations..
Et le nombre d'opérations va croissant en fonction du nombre de dimensions..
Merci pour tes remarques, je suis parfaitement d'accord avec les inconvénients et les avantages que tu soulignes, je pense qu'à terme je partirai vers cette solution.
Tout le code s'appuie sur ce tableau et les dimensions X,Y,Z, il y a beaucoup de travail, donc commencer ce chantier maintenant me retarderai sur les objectifs à plus court terme même si après je serai gagnant en réfléchissant et en adoptant cette solution.
Dans l'ordre, il convient d'allouer dynamiquement la mémoire de ce tableau pour ne pas prendre du retard dans les simulations et optimiser progressivement le code.
Oui et non, en faite la solution de souviron est celle qui te faut dans ton cas, et ca ne te prendra pas beaucoups de temp pour comprendre. d'ailleur avec un tableau a une demension tu peux avoir deux approches.
1/ soit les dimensions contigue: XYZM XYZM XYZM c'est bien mais si dim(X)=dim(des autres)
2/ soit tu possedes par plan. soit 4 plan avec pour chaque plan un index pour conaitre la position du premier element du plan suivant c'est ce que je te conseille:
XXXXXXXXXYYYYYYYYZZZZZZMMMMMMMMM
donc en code ca donne:bon c'est un peu simplet comme exemple(c'est la premiere idee qui m'est venue a l'esprit). mais en gros pour x4,y4,z4,m4 on a respectivement tab1d[0+4] tab1d[dim1+4] tab1d[dim1+dim2+4] tab1d[dim1+dim2+dim3+4]
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13 int size = dim1+dim2+dim3+dim4;//sachant que les dims sont deja declare int tab1d = (int *) malloc(sizeof(int)*size); /* initialisation de tout les X*/ int i; for(i=0;i<dim1;++) tab1d[i] = quelquechose; /* plus generalement */ decalage = dimN+...+dimM //avec N,M E [0;4[ et N<M et dim0=0 //ex; on veut les Y donc decalage = dim1 for(i=0;i<dimx;++i) tab1d[decalage+i] = untruc; free(tab1d) // la liberation devient donc plus simple
Merci à vous pour toutes ces idées débordantes. Je vais prendre le temps d'étudier tout ça mais pour l'instant je reviens sur la solution du tableau 4D. En tenant compte de tes remarques ci-dessous :
Voici ce que je propose :
ok pour la compilation et l'exécution mais je souhaiterai avoir votre regard sur ce code avant son utilisation dans un grand code. Encore merci pour vos contributions.
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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119 #include <stdio.h> #include <math.h> #include <stdlib.h> void AllocationDynamique_4D(int *****tab4d, int dim1, int dim2, int dim3, int dim4); void AffichageTableau_4D(int ****tableau, int dim1, int dim2, int dim3, int dim4); void RemplirTableau_4D(int ****tableau, int dim1, int dim2, int dim3, int dim4); void LibereTableau_4D(int *****tableau, int dim1, int dim2, int dim3); int main(int argc, char *argv[]) { int i,j,k; int ****tab4d; int dimension1; int dimension2; int dimension3; int dimension4; dimension1=1; dimension2=2; dimension3=2; dimension4=2; AllocationDynamique_4D(&tab4d,dimension1,dimension2,dimension3,dimension4); RemplirTableau_4D(tab4d,dimension1,dimension2,dimension3,dimension4); AffichageTableau_4D(tab4d,dimension1,dimension2,dimension3,dimension4); LibereTableau_4D(&tab4d,dimension1,dimension2,dimension3); return EXIT_SUCCESS; } /* Fin du programme principal */ void AllocationDynamique_4D(int *****tab4d, int dim1, int dim2, int dim3, int dim4) { int i, j, k; *tab4d=calloc(dim1, sizeof(int***)); int ****p=*tab4d; for(i= 0; i < dim1; i++){ p[i]= (int ***)calloc(dim2, sizeof(int**)); for(j= 0; j < dim2; j++){ p[i][j]= (int **)calloc(dim3, sizeof(int*)); for(k= 0; k < dim3; k++){ p[i][j][k]= (int *)calloc(dim4, sizeof(int)); } } } if(p==NULL){printf("Allocation impossible\n");exit(-1);} } void AffichageTableau_4D(int ****tableau, int dim1, int dim2, int dim3, int dim4) { int i,j,k,l; for(i=0;i<dim1;i++){ for(j=0;j<dim2;j++){ for(k=0;k<dim3;k++){ for(l=0;l<dim4;l++){ printf("%d\n",tableau[i][j][k][l]); } } } } } void RemplirTableau_4D(int ****tableau, int dim1, int dim2, int dim3, int dim4) { int i,j,k,l; for(i=0;i<dim1;i++){ for(j=0;j<dim2;j++){ for(k=0;k<dim3;k++){ for(l=0;l<dim4;l++){ tableau[i][j][k][l]=4; } } } } } void LibereTableau_4D(int *****tableau, int dim1, int dim2, int dim3) { int i,j,k; int ****p=*tableau; if(p!=NULL){ for (i=0; i<dim1; i++){ for (j=0; j<dim2; j++){ for (k=0; k<dim3; k++){ free(p[i][j][k]); } free(p[i][j]); } free(p[i]); } free(p); }else{printf("Deallocation impossible\n");exit(-1);} }
Salut,
J'avoue ne pas avoir tout lu mais je pense que en général, un tableau de plus de 2 dimensions est une erreur de conception. Enfin peut-être que dans ton cas, c'est une nécessité.
Malgré tout, tu ne pourrais pas utiliser des structures plutot ?
Par exemple tu pourrais représenter un voxel comme ceci :
Je ne connais pas trop ton exercice donc je ne veux pas trop m'avancer en disant ça, donc si il y a d'autres avis favorables... Même si la structure proposé au dessus ne convient pas, c'est peut-être une façon de résoudre ton exercice plus simplement ?
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9 typedef struct{ int x; int y; int z; voxel* voisins ; } voxel ; typedef cube voxel[nb_voxels] ;
Salut,
Je suis d’accord sur ce qui a été dit précédemment et aussi sur ce que tu viens de proposer. Le problème est que j'ai repris un code. Ce tableau joue un rôle important dans le processus de calcul et tout le code repose sur celui-ci donc pour l'instant je n'ai pas trop le feu vert de transformer entièrement le code. L'urgence serait plutôt d'allouer dynamiquement de la mémoire à ce tableau afin de produire... et revenir après sur le code pour optimiser en adoptant des solutions plus adaptées.
Vos remarques sont vraiment les bienvenues et je vous remercie tous pour toutes ces solutions.
Quelqu'un peut il donner un avis sur le code suivant ?
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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119 #include <stdio.h> #include <math.h> #include <stdlib.h> void AllocationDynamique_4D(int *****tab4d, int dim1, int dim2, int dim3, int dim4); void AffichageTableau_4D(int ****tableau, int dim1, int dim2, int dim3, int dim4); void RemplirTableau_4D(int ****tableau, int dim1, int dim2, int dim3, int dim4); void LibereTableau_4D(int *****tableau, int dim1, int dim2, int dim3); int main(int argc, char *argv[]) { int i,j,k; int ****tab4d; int dimension1; int dimension2; int dimension3; int dimension4; dimension1=1; dimension2=2; dimension3=2; dimension4=2; AllocationDynamique_4D(&tab4d,dimension1,dimension2,dimension3,dimension4); RemplirTableau_4D(tab4d,dimension1,dimension2,dimension3,dimension4); AffichageTableau_4D(tab4d,dimension1,dimension2,dimension3,dimension4); LibereTableau_4D(&tab4d,dimension1,dimension2,dimension3); return EXIT_SUCCESS; } /* Fin du programme principal */ void AllocationDynamique_4D(int *****tab4d, int dim1, int dim2, int dim3, int dim4) { int i, j, k; *tab4d=calloc(dim1, sizeof(int***)); int ****p=*tab4d; for(i= 0; i < dim1; i++){ p[i]= (int ***)calloc(dim2, sizeof(int**)); for(j= 0; j < dim2; j++){ p[i][j]= (int **)calloc(dim3, sizeof(int*)); for(k= 0; k < dim3; k++){ p[i][j][k]= (int *)calloc(dim4, sizeof(int)); } } } if(p==NULL){printf("Allocation impossible\n");exit(-1);} } void AffichageTableau_4D(int ****tableau, int dim1, int dim2, int dim3, int dim4) { int i,j,k,l; for(i=0;i<dim1;i++){ for(j=0;j<dim2;j++){ for(k=0;k<dim3;k++){ for(l=0;l<dim4;l++){ printf("%d\n",tableau[i][j][k][l]); } } } } } void RemplirTableau_4D(int ****tableau, int dim1, int dim2, int dim3, int dim4) { int i,j,k,l; for(i=0;i<dim1;i++){ for(j=0;j<dim2;j++){ for(k=0;k<dim3;k++){ for(l=0;l<dim4;l++){ tableau[i][j][k][l]=4; } } } } } void LibereTableau_4D(int *****tableau, int dim1, int dim2, int dim3) { int i,j,k; int ****p=*tableau; if(p!=NULL){ for (i=0; i<dim1; i++){ for (j=0; j<dim2; j++){ for (k=0; k<dim3; k++){ free(p[i][j][k]); } free(p[i][j]); } free(p[i]); } free(p); }else{printf("Deallocation impossible\n");exit(-1);} }
Il y a quelques petites choses à améliorer pour rendre le code moins lourd et donc, plus clair :
1)
2)
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5 int dimension1 = 1; int dimension2 = 2; int dimension3 = 2; int dimension4 = 2;
Il ne faut le faire tout à la fin mais après chaque appel à calloc ou malloc.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2 if(p==NULL){printf("Allocation impossible\n");exit(-1);}
3)
Pourquoi pas ?
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4 *tab4d=calloc(dim1, sizeof(int***)); int ****p=*tab4d;
4)
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2 ****p = calloc(dim1, sizeof(int***) );
Si tes dimensions ne changent pas tu peux utiliser des defines, ça te permettrait d'éviter d'avoir à passer 4 arguments dim1, dim2, ...
5)
Je reviens à l'attaque avec la structure proposée ci-dessus. Par exemple, tu pourrais décider de ne stocker que un point de ton voxel en mémoire, les autres étant déductibles.
Bonne chance en tout cas.
tu supposes que si p est non nul alors p[i] (et les autres pointeurs aussi) est non nul.
visiblement c'est le cas. mais ta machine elle ne suppose pas donc avant chaque free
test le pointeur etant donnee que alloc et free ne sont pas dans la meme fonction donc fait
de maniere general
Code : Sélectionner tout - Visualiser dans une fenêtre à part if(p[i]!=NULL) free(p[i]);
dans la meme fonction tu peux faire:
mais quand tu as juste une fonction qui fait les free vaut mieux tester, car cette fonction pour avoir une utilisation general ne sais pas ou et quand et si les allocations ont bien reussit:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7 int *p=(int *) malloc(sizeof(int)*x); if(p==NULL) exit(-1); ... ... ... free(p);dans ton cas c'est pas grave puisque si un allloc echoue ton programme s'arrete, mais si tu veux utiliser ta fonction plus tard dans un projet et que d'autre partie sont ecrite pas un autre, qui testes pas ses pointeurs tu aurras des truc genredouble free corruption, ou erreur de segmentation a l'execution.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14 int funcalloc(int **p) { int *q=*p; q=(int *)malloc(sizeof(int)*x); if(q==NULL) return -1; return 0; } void libere(int **p) { int *q=*p; if(q!=NULL) free(q); }
tu vois dans mon cas que il y a -1 si les allocs marches pas et 0 si oui.
si tu ne vois pas l'interret de continue apres un echec d'alllocation imagine un petit jeu qui n'a pas besoin de charger quoique ce soit en memoire. donc a chaque utilisation il marche avec des variables non pointeur. mais il a besoin de charger un fichier audio qui lui sera associe a un pointeur. si l'allocation echoue je ne fait pas exit car je veux quand meme jouer a mon jeu sans son. donc pour ne pas faire de cas par cas je vais a chaque fois supposer que l'allocation n'a pas echouer et dans la fonction liberer tester avant de faire free.
je te conseil donc d'ajouter un if avant chaque free dans ta fonction de liberation
A la compilation je ne connais pas à priori dimension1, dimension2, dimension3, dimension4 ne sont pas connues.
Dans la version actuelle, les defines sont utilisées pour dimensionner le tableau mais à chaque fois qu'on veut changer ces dimensions il faut modifier la source et compiler, il serait plus souple de rentrer ces informations dans un fichier paramètre qui est lu au tout début du calcul.
pour la compiler la source sans connaître à priori ces dimensions et ensuite ajuster ce tableau au cours du calcul me conduisent donc à l'allocation dynamique.
ici les valeurs sont prises simplement pour illustrer ce que je fais dans le code...
d'autre part, comme on te l'a déjà fait remarquer, faire des exit n'est pas correct...
Il vaut mieux libérer la mémoire à ce niveau et remonter une erreur..
A défaut, utiliser atexit (mais c'est mieux de faire remonter un code d'erreur)...
Voici une nouvelle proposition :
Qu'en pensez-vous?
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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87 #include <stdio.h> #include <math.h> #include <stdlib.h> void AllocationDynamique_4D(int *****tab4d, int dim1, int dim2, int dim3, int dim4); void LibereTableau_4D(int *****tableau, int dim1, int dim2, int dim3); int main(int argc, char *argv[]) { int i,j,k; int ****tab4d; int dimension1; int dimension2; int dimension3; int dimension4; dimension1=1; dimension2=2; dimension3=2; dimension4=2; AllocationDynamique_4D(&tab4d,dimension1,dimension2,dimension3,dimension4); LibereTableau_4D(&tab4d,dimension1,dimension2,dimension3); return EXIT_SUCCESS; } /* Fin du programme principal */ void AllocationDynamique_4D(int *****tab4d, int dim1, int dim2, int dim3, int dim4) { int i, j, k; int e=0; *tab4d=calloc(dim1, sizeof(int***)); int ****p=*tab4d; if(p==NULL){e=-1;} for(i= 0; i < dim1; i++){ p[i]= (int ***)calloc(dim2, sizeof(int**)); if(p[i]==NULL){e=-2;} for(j= 0; j < dim2; j++){ p[i][j]= (int **)calloc(dim3, sizeof(int*)); if(p[i][j]==NULL){e=-3;} for(k= 0; k < dim3; k++){ p[i][j][k]= (int *)calloc(dim4, sizeof(int)); if(p[i][j][k]==NULL){e=-4;} } } } if(e<0){printf("Allocation impossible au niveau de e =%d \n",e);} } void LibereTableau_4D(int *****tableau, int dim1, int dim2, int dim3) { int i,j,k; int ****p=*tableau; int e=0; for (i=0; i<dim1; i++){ for (j=0; j<dim2; j++){ for (k=0; k<dim3; k++){ if(p[i][j][k]!=NULL){free(p[i][j][k]);}else{e=-1;} } if(p[i][j]!=NULL){free(p[i][j]);}else{e=-2;} } if(p[i]!=NULL){free(p[i]);}else{e=-3;} } if(p!=NULL){free(p);}else{e=-4;} if(e<0){printf("Desallocation impossible au niveau de e =%d \n",e);} }
d'abord je ne suis pas d'accord avec la remarque de Trademark concernant les if () ou non...
Il y a des cas où le style qu'il préconise est correct, mais pas dans le genre de cas où on doit tester de suite..
Je n'écrirais donc pas :
mais :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2 p[i]= (int ***)calloc(dim2, sizeof(int**)); if(p[i]==NULL){e=-2;}
D'autre part, quand on fait ça, il faut un else.. sinon tu continues et va droit au crash...
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2 if ( (p[i]= (int ***)calloc(dim2, sizeof(int**)) == NULL ) {e=-2;}
Enfin, pour être propre, si une allocation échoue à i, il faut libérer tout ce qui é été alloué avant avant de de ressortir..
Dans ton cas, par exemple :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14 if ( (p[i]= (int ***)calloc(dim2, sizeof(int**)) == NULL ) { if ( i > 0 ) for ( j = (i-1) ; j >= 0 ; j-- ) { /* on doit libérer tout ce qui a été alloué sous p[j] */ free(p[j]); } free(p), p=NULL ; e = -2 ; break ; }
Le if n'est pas obligatoire : free(NULL) est correct et de comportement bien défini (il ne fait rien dans ce cas).
Code : Sélectionner tout - Visualiser dans une fenêtre à part if(p[i]!=NULL) free(p[i]);
Par contre, selon le cas, ceci peut être indispensable :
Ce que je verrais bien pour clarifier le code est :
Code : Sélectionner tout - Visualiser dans une fenêtre à part if(p!=NULL) free(p[i]);
Et pour faire bien propre, tester correctement l'allocation dynamique et récupérer la mémoire en cas d'échec. Par exemple :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10 typedef struct { int **** tab; int dim[4]; //ou int dim1; int dim2; int dim3; int dim4; } TTableau; TTableau * AllocationDynamique_4D(int dim1, int dim2, int dim3, int dim4); void AffichageTableau_4D(TTableau * tableau); void RemplirTableau_4D(TTableau * tableau); void LibereTableau_4D(TTableau * tableau);
avec par exemple :
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 TTableau * AllocationDynamique_4D(int dim1, int dim2, int dim3, int dim4) { int i, j, k; TTableau * tableau = malloc(sizeof *tableau); int errorAlloc = tableau==NULL; if(!errorAlloc) { tableau->dim[0] = dim1; tableau->dim[1] = dim2; tableau->dim[2] = dim3; tableau->dim[3] = dim4; tableau->tab = malloc(dim1*sizeof(int***)); errorAlloc = errorAlloc || tableau->tab==NULL; if(!errorAlloc) { for(i=0; i<dim1 && !errorAlloc; i++) { tableau->tab[i] = malloc(dim2*sizeof(int**)); errorAlloc = errorAlloc || tableau->tab[i]==NULL; if(!errorAlloc && i<dim1-1)tableau->tab[i+1] = NULL; for(j=0; j<dim2 && !errorAlloc; j++) { tableau->tab[i][j] = malloc(dim3*sizeof(int*)); errorAlloc = errorAlloc || tableau->tab[i][j]==NULL; if(!errorAlloc && j< dim2-1)tableau->tab[i][j+1] = NULL; for(k=0; k<dim3 && !errorAlloc; k++) { tableau->tab[i][j][k] = malloc(dim4*sizeof(int)); errorAlloc = errorAlloc || tableau->tab[i][j][k]==NULL; if(!errorAlloc && k<dim3-1)tableau->tab[i][j][k+1] = NULL; } } } } } if(errorAlloc) { LibereTableau_4D(tableau); tableau = NULL; } return tableau; //--------------------------------------------------------------------------- void LibereTableau_4D(TTableau * tableau) { int i, j, k; if(tableau!=NULL) { if(tableau->tab!=NULL) { for(i=0; i<tableau->dim[0] && tableau->tab[i]!=NULL; i++) { for(j=0; j<tableau->dim[1] && tableau->tab[i][j]!=NULL; j++) { for(k= 0; k<tableau->dim[2] && tableau->tab[i][j][k]!=NULL; k++) free(tableau->tab[i][j][k]); free(tableau->tab[i][j]); } free(tableau->tab[i]); } free(tableau->tab); } free(tableau); } }
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12 int main(void) { TTableau *p = AllocationDynamique_4D(3,5,7,11); if(p) { RemplirTableau_4D(p); AffichageTableau_4D(p); LibereTableau_4D(p) , p = NULL; } else printf("Erreur d'allocation\n"); return 0; }
Vous avez un bloqueur de publicités installé.
Le Club Developpez.com n'affiche que des publicités IT, discrètes et non intrusives.
Afin que nous puissions continuer à vous fournir gratuitement du contenu de qualité, merci de nous soutenir en désactivant votre bloqueur de publicités sur Developpez.com.
Partager