IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

 C Discussion :

Allocation dynamique tableaux 4 dimensions


Sujet :

C

  1. #21
    Membre du Club
    Profil pro
    Inscrit en
    Mai 2008
    Messages
    122
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2008
    Messages : 122
    Points : 66
    Points
    66
    Par défaut
    Citation Envoyé par Lucien63 Voir le message
    Non pas du tout !

    tab4d n'est pas la même chose que *tab4d
    Le deuxième utilise l'opérateur de déréférencement de pointeur.
    peux-tu expliquer un peu?

  2. #22
    Membre confirmé
    Inscrit en
    Juillet 2005
    Messages
    512
    Détails du profil
    Informations forums :
    Inscription : Juillet 2005
    Messages : 512
    Points : 641
    Points
    641
    Par défaut
    Et bien cet opérateur permet d'accéder à la valeur contenu dans le bloc mémoire ou le pointeur pointe.

    ex :

    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);
    Dans ce code px pointe sur x (px contient l'adresse de x)
    quand je fait *px = 20 , c'est la valeur de x que je modifie.

  3. #23
    Membre du Club
    Profil pro
    Inscrit en
    Mai 2008
    Messages
    122
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2008
    Messages : 122
    Points : 66
    Points
    66
    Par défaut
    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) :

    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);
     
    }
    Merci de m'avoir accompagner dans cette épreuve.

  4. #24
    Membre chevronné
    Avatar de lilington
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2005
    Messages
    681
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : Chine

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Juin 2005
    Messages : 681
    Points : 1 802
    Points
    1 802
    Par défaut
    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:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    int ****p = *tab4d;
    p=malloc(....)
    ....
    *tab4d = p;
    de meme pour la suppression:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    int ****p= *tab4d;
    .....liste des free;
    ....
    free(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.

  5. #25
    Membre du Club
    Profil pro
    Inscrit en
    Mai 2008
    Messages
    122
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2008
    Messages : 122
    Points : 66
    Points
    66
    Par défaut
    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.


    Citation Envoyé par lilington Voir le message
    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:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    int ****p = *tab4d;
    p=malloc(....)
    ....
    *tab4d = p;
    de meme pour la suppression:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    int ****p= *tab4d;
    .....liste des free;
    ....
    free(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.
    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 :

    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);
    }
    et à la libération :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    if(p!=NULL)
    {
      free(p)
    }

  6. #26
    Membre chevronné
    Avatar de lilington
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2005
    Messages
    681
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : Chine

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Juin 2005
    Messages : 681
    Points : 1 802
    Points
    1 802
    Par défaut
    juste une question a tout hasard et pour satisfaire ma curiosite, pourquoi tu as besoin de 4 dimensions?

  7. #27
    Membre du Club
    Profil pro
    Inscrit en
    Mai 2008
    Messages
    122
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2008
    Messages : 122
    Points : 66
    Points
    66
    Par défaut
    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 :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    tableau[X][Y][Z][NC]
    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
    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...
    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.

    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.

  8. #28
    Expert éminent sénior

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 610
    Détails du profil
    Informations personnelles :
    Âge : 66
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 610
    Points : 17 923
    Points
    17 923
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par mecaplus Voir le message
    C'est donc un tableau statique. Le code tourne sans problème mais on est très vite limiter par la taille du système.

    A chaque fois on veut changer la taille du système il faut modifier la source et plusieurs tableaux de dimensions inférieures sont dimensionner 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..

  9. #29
    Membre du Club
    Profil pro
    Inscrit en
    Mai 2008
    Messages
    122
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2008
    Messages : 122
    Points : 66
    Points
    66
    Par défaut
    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.

  10. #30
    Membre chevronné
    Avatar de lilington
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2005
    Messages
    681
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : Chine

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Juin 2005
    Messages : 681
    Points : 1 802
    Points
    1 802
    Par défaut
    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:
    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
    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]

  11. #31
    Membre du Club
    Profil pro
    Inscrit en
    Mai 2008
    Messages
    122
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2008
    Messages : 122
    Points : 66
    Points
    66
    Par défaut
    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 :


    Citation Envoyé par lilington Voir le message
    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:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    int ****p = *tab4d;
    p=malloc(....)
    ....
    *tab4d = p;
    de meme pour la suppression:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    int ****p= *tab4d;
    .....liste des free;
    ....
    free(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.
    Voici ce que je propose :

    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);}
     
    }
    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.

  12. #32
    Membre expérimenté Avatar de Trademark
    Profil pro
    Inscrit en
    Février 2009
    Messages
    762
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2009
    Messages : 762
    Points : 1 396
    Points
    1 396
    Par défaut
    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 :

    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] ;
    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 ?

  13. #33
    Membre du Club
    Profil pro
    Inscrit en
    Mai 2008
    Messages
    122
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2008
    Messages : 122
    Points : 66
    Points
    66
    Par défaut
    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);}
     
    }

  14. #34
    Membre expérimenté Avatar de Trademark
    Profil pro
    Inscrit en
    Février 2009
    Messages
    762
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2009
    Messages : 762
    Points : 1 396
    Points
    1 396
    Par défaut
    Il y a quelques petites choses à améliorer pour rendre le code moins lourd et donc, plus clair :

    1)
    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;
    2)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    if(p==NULL){printf("Allocation impossible\n");exit(-1);}
    Il ne faut le faire tout à la fin mais après chaque appel à calloc ou malloc.

    3)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
     *tab4d=calloc(dim1, sizeof(int***));
     
     int ****p=*tab4d;
    Pourquoi pas ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    ****p = calloc(dim1, sizeof(int***) );
    4)
    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.

  15. #35
    Membre chevronné
    Avatar de lilington
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2005
    Messages
    681
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : Chine

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Juin 2005
    Messages : 681
    Points : 1 802
    Points
    1 802
    Par défaut
    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
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if(p[i]!=NULL) free(p[i]);
    de maniere general
    dans la meme fonction tu peux faire:
    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);
    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
    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);
    }
    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.
    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

  16. #36
    Membre du Club
    Profil pro
    Inscrit en
    Mai 2008
    Messages
    122
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2008
    Messages : 122
    Points : 66
    Points
    66
    Par défaut
    Citation Envoyé par Trademark Voir le message

    4)
    Si tes dimensions ne changent pas tu peux utiliser des defines, ça te permettrait d'éviter d'avoir à passer 4 arguments dim1, dim2, ...
    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...

  17. #37
    Expert éminent sénior

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 610
    Détails du profil
    Informations personnelles :
    Âge : 66
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 610
    Points : 17 923
    Points
    17 923
    Billets dans le blog
    2
    Par défaut
    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)...

  18. #38
    Membre du Club
    Profil pro
    Inscrit en
    Mai 2008
    Messages
    122
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2008
    Messages : 122
    Points : 66
    Points
    66
    Par défaut
    Voici une nouvelle proposition :
    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);}
     
    }
    Qu'en pensez-vous?

  19. #39
    Expert éminent sénior

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 610
    Détails du profil
    Informations personnelles :
    Âge : 66
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 610
    Points : 17 923
    Points
    17 923
    Billets dans le blog
    2
    Par défaut
    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 :

    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;}
    mais :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    	  if ( (p[i]= (int ***)calloc(dim2, sizeof(int**)) == NULL )
    	  {e=-2;}
    D'autre part, quand on fait ça, il faut un else.. sinon tu continues et va droit au crash...

    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 ;
              }

  20. #40
    Expert éminent sénior
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Points : 13 926
    Points
    13 926
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if(p[i]!=NULL) free(p[i]);
    Le if n'est pas obligatoire : free(NULL) est correct et de comportement bien défini (il ne fait rien dans ce cas).
    Par contre, selon le cas, ceci peut être indispensable :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if(p!=NULL) free(p[i]);
    Ce que je verrais bien pour clarifier le code est :
    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);
    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
    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);
        }
    }
    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
    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;
    }

Discussions similaires

  1. decalaration dynamique tableaux deux dimensions et TRI
    Par Alex35 dans le forum Général JavaScript
    Réponses: 5
    Dernier message: 27/12/2007, 13h48
  2. Tableaux 2 dimensions dynamiques
    Par onegamer dans le forum Struts 1
    Réponses: 1
    Dernier message: 06/07/2006, 12h55
  3. allocation dynamique et tableaux de pointeurs
    Par gbardy dans le forum 4D
    Réponses: 3
    Dernier message: 06/07/2006, 11h08
  4. Réponses: 6
    Dernier message: 26/11/2005, 19h55
  5. Réponses: 4
    Dernier message: 03/12/2002, 16h47

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo