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 :

tableau 2D et allocation dynamique


Sujet :

C

  1. #1
    Membre éprouvé

    Profil pro
    Inscrit en
    Juin 2006
    Messages
    1 116
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 1 116
    Points : 1 111
    Points
    1 111
    Par défaut tableau 2D et allocation dynamique
    Bonjour.
    J'ai consulté la FAQ à ce sujet, et je voulais savoir s'il y un moyen de spécifier un type "tableau 2D". Est ce que la construction suivante est juste pour un constructeur ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    typedef double * ligne;
    typedef ligne * tableau2D;
    const long taille=10000;
    tableau2D tab;
    tab=malloc(sizeof(ligne)*taille)
    for(i=0;i<taille;i++)
       {
       tab[i]=malloc(sizeof(tableau2D)*taille)
       }
    Désolé si c'est tout faux, je crois que je n'ai pas tout compris à la réponse dans la FAQ.

  2. #2
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 518
    Points
    41 518
    Par défaut
    Presque, petite erreur sur le sizeof.
    --> Évite le sizeof() sur les types.

    [Code incorrect censuré]

    TEST DU CODE EN COURS
    • Ça compile
    • Mais ça ne marchera pas bien (je n'ai même pas testé l'exécution, puisque j'ai vu des erreurs dans mon code).
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  3. #3
    Membre éclairé Avatar de stephl
    Profil pro
    Développeur informatique
    Inscrit en
    Février 2007
    Messages
    643
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Février 2007
    Messages : 643
    Points : 771
    Points
    771
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    typedef double *LIGNE;
    typedef LIGNE *TABLEAU2D;
     
    const long nblignes=100,nbcols=50;
    TABLEAU2D tab;
     
    if ((tab=(TABLEAU2D) malloc(nblignes*sizeof (LIGNE)))==NULL)
    ...
    for (i=0;i<nblignes;++i)
     if ((tab[i]=(LIGNE) malloc(nbcols*sizeof (double)))==NULL)
      ...

  4. #4
    Expert éminent sénior

    Avatar de fearyourself
    Homme Profil pro
    Ingénieur Informaticien Senior
    Inscrit en
    Décembre 2005
    Messages
    5 121
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur Informaticien Senior
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2005
    Messages : 5 121
    Points : 11 877
    Points
    11 877
    Par défaut
    Citation Envoyé par stephl
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    typedef double *LIGNE;
    typedef LIGNE *TABLEAU2D;
     
    const long nblignes=100,nbcols=50;
    TABLEAU2D tab;
     
    if ((tab=(TABLEAU2D) malloc(nblignes*sizeof (LIGNE)))==NULL)
    ...
    for (i=0;i<nblignes;++i)
     if ((tab[i]=(LIGNE) malloc(nbcols*sizeof (double)))==NULL)
      ...
    Masquer des pointeurs

    Ce n'est que Force 6 sur l'échelle du goret... De plus, tu cast le retour du malloc (force 5)...

    Lien

    Jc

  5. #5
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 518
    Points
    41 518
    Par défaut
    Mon code, testé et corrigé:
    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
    #include <stdlib.h>
    #include <stdio.h>
     
    #ifdef _DEBUG
    #define DBG_PRINTF(a) printf a
    #else
    #define DBG_PRINTF(a)
    #endif
     
    /* Fonction d'allocation
       --------------------- */
    double ** AllocTable2D(
     size_t taille1, /*[in] Nb de lignes */
     size_t taille2  /*[in] Nb de valeurs par ligne */
     )
    {
        double ** ppValeurs;
     
        DBG_PRINTF((" Allocation d'un tableau de %u pointeurs...\n", (unsigned int)taille1));
        ppValeurs = malloc(sizeof(*ppValeurs)*taille1);
        if(ppValeurs != NULL)
        {
            size_t i;
            /* Initialiser tous les pointeurs à NULL
               Pour mieux libérer en cas d'échec */
            DBG_PRINTF((" Initialisation des pointeurs a NULL...\n"));
            for(i=0 ; i<taille1 ; ++i)
                ppValeurs[i] = NULL;
     
            /* Allocations des lignes */
            DBG_PRINTF((" Allocation de %u valeurs pour chaque pointeur...\n", (unsigned int)taille2));
            for(i=0 ; i<taille1 ; ++i)
            {
                double *pValeurs = malloc(sizeof(*pValeurs)*taille2);
                if(pValeurs==NULL)
                    break;
                ppValeurs[i] = pValeurs;
            }
     
            /* Si echec, libérer les ressources */
            if(i < taille1)
            {
                size_t j;
                DBG_PRINTF((" Echec apres %u pointeurs. Destruction...\n", (unsigned int)i));
                /* Rappel: free(NULL) ne fait rien (inoffensif). */
                for(j=0 ; j<i ; ++j)
                    free(ppValeurs[j]), ppValeurs[j]=NULL;
                free(ppValeurs), ppValeurs = NULL;
            }
        }/*if*/
        return ppValeurs;
    }
     
    /* Fonction de destruction
       ----------------------- */
    void FreeTable2D(double **ppValeurs, size_t taille1)
    {
        if(ppValeurs != NULL)
        {
            size_t i;
            for(i=0 ; i<taille1 ; ++i)
                free(ppValeurs[i]), ppValeurs[i]=NULL;
            free(ppValeurs), ppValeurs = NULL;
        }
    }
     
    /* Fonction de test
       ---------------- */
    void TestArrayC(void)
    {
        void const *pvPrintf;
        size_t const taille1 = 4200, taille2 = 14400;
        double **ppValeurs;
     
        puts("Allocation...");
        ppValeurs = AllocTable2D(taille1, taille2);
     
        pvPrintf = ppValeurs;
        printf("ppValeurs = %p\n", pvPrintf);
     
        puts("Destruction...");
        FreeTable2D(ppValeurs, taille1), ppValeurs=NULL;
    }
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  6. #6
    Membre éclairé Avatar de stephl
    Profil pro
    Développeur informatique
    Inscrit en
    Février 2007
    Messages
    643
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Février 2007
    Messages : 643
    Points : 771
    Points
    771
    Par défaut
    Citation Envoyé par fearyourself
    Masquer des pointeurs

    Ce n'est que Force 6 sur l'échelle du goret... De plus, tu cast le retour du malloc (force 5)...

    Lien

    Jc
    Chacun sa façon de voir. Il suffit de savoir ce que l'on fait. Personnellement, je préfère caster le retour de malloc(): cela me force à vérifier que je ne fais pas n'importe quoi .

  7. #7
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 518
    Points
    41 518
    Par défaut
    @stephl: Au contraire, le cast du retour de malloc() peut masquer une erreur.

    Quoi qu'il en soit, je préfère minimiser le nombre d'allocations pour ce genre de tableaux.
    Je trouve ces fonctions plus simples:
    Code C : 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
    #include <stdlib.h>
    #include <stdio.h>
     
    #ifdef _DEBUG
    #define DBG_PRINTF(a) printf a
    #else
    #define DBG_PRINTF(a)
    #endif
     
    /* Autre fonction d'allocation
       --------------------------- */
    double ** AutreAllocTable2D(
     size_t taille1, /*[in] Nb de lignes */
     size_t taille2  /*[in] Nb de valeurs par ligne */
     )
    {
        double ** ppValeurs;
        size_t const taille1x2 = taille1*taille2;
        if(taille1x2 / taille2 != taille1)
            return NULL; /*Débordement des tailles*/
     
        DBG_PRINTF((" Allocation d'un tableau de %lu pointeurs...\n", (unsigned long)taille1));
        ppValeurs = malloc(sizeof(*ppValeurs)*taille1);
        if(ppValeurs != NULL)
        {
            double * pValeurs;
            DBG_PRINTF((" Allocation d'un tableau de %lu*%lu=%lu valeurs...\n",
             (unsigned long)taille1, (unsigned long)taille2, (unsigned long)taille1x2
             ));
            pValeurs = malloc(sizeof(*pValeurs)*taille1x2);
            if(pValeurs != NULL)
            {
                size_t i;
                /* Affecter tous les pointeurs */
                DBG_PRINTF((" Affectation des pointeurs...\n"));
                for(i=0 ; i<taille1 ; ++i)
                    ppValeurs[i] = pValeurs + (i*taille2);
            }
            else
            {
                /* Echec de la seconde allocation, liberer la premiere */
                DBG_PRINTF((" Echec de la seconde allocation.\n"));
                free(ppValeurs), ppValeurs=NULL;
            }
        }/*if*/
        return ppValeurs;
    }
     
    /* Autre fonction de destruction
       ----------------------------- */
    void AutreFreeTable2D(double **ppValeurs)
    {
        if(ppValeurs != NULL)
        {
            free(ppValeurs[0]);
            free(ppValeurs);
        }
    }
     
    /* Fonction de test
       ---------------- */
    void TestArrayC(void)
    {
        void const *pvPrintf;
        size_t const taille1 = 4200, taille2 = 14400;
        double **ppValeurs1;
        double **ppValeurs2;
     
        puts("Allocation...");
        ppValeurs1 = AllocTable2D(taille1, taille2);
     
        pvPrintf = ppValeurs1;
        printf("ppValeurs1 = %p\n", pvPrintf);
     
        puts("Destruction...");
        FreeTable2D(ppValeurs1, taille1), ppValeurs1=NULL;
     
        puts("Allocation...");
        ppValeurs2 = AutreAllocTable2D(taille1, taille2);
     
        pvPrintf = ppValeurs2;
        printf("ppValeurs2 = %p\n", pvPrintf);
     
        puts("Destruction...");
        AutreFreeTable2D(ppValeurs2), ppValeurs2=NULL;
    }
    Edit: Une paire de petits schémas illustrant les différents concepts :

    Et aussi la version sans les printf.
    Et La version C++.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  8. #8
    Membre éprouvé

    Profil pro
    Inscrit en
    Juin 2006
    Messages
    1 116
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 1 116
    Points : 1 111
    Points
    1 111
    Par défaut
    Citation Envoyé par Médinoc
    Presque, petite erreur sur le sizeof.
    --> Évite le sizeof() sur les types.
    ...
    TEST DU CODE EN COURS
    • Ça compile
    • Mais ça ne marche pas bien.
    Ça ne marche pas bien signifie "segmentation fault" ou juste que ça rame à l'exécution ? (Je n'ai pas testé le code)

    EDIT:vous construisez des fonctions plus vite que votre ombre.

    (Digression : savez vous où je peux retrouver les flags de GCC pour un code ... conforme, enfin régulier, enfin qui veut dire quelque chose, enfin pas du code de goret quoi = "mode parano")

  9. #9
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 518
    Points
    41 518
    Par défaut
    J'ai montré le défaut que je reproche aux autres
    En fait, je ne suis même pas allé jusqu'à tester l'exécution de ce code, car j'ai vu que j'avais fait une erreur dedans.
    Alors, je n'ai testé que le code corrigé.

    Edit: D'ailleurs, ça montre bien qu'il est facile de se tromper pour les premières fonctions. Je préfère les secondes...

    PS: http://emmanuel-delahaye.developpez....tm#cfg_compilo
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

Discussions similaires

  1. Allocation dynamique tableau dans structure
    Par chental dans le forum C
    Réponses: 2
    Dernier message: 03/08/2006, 09h03
  2. [PRO*C] Allocation dynamique d'un tableau de VARCHAR
    Par NéalZheimer dans le forum Interfaces de programmation
    Réponses: 5
    Dernier message: 07/07/2006, 13h02
  3. Réponses: 6
    Dernier message: 26/11/2005, 19h55
  4. Réponses: 18
    Dernier message: 06/07/2005, 14h58
  5. [Tableau] Allocation dynamique du contenu
    Par VincenzoR dans le forum Collection et Stream
    Réponses: 8
    Dernier message: 08/05/2004, 20h57

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