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 dynamique contigu


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé
    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    421
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2011
    Messages : 421
    Par défaut tableau dynamique contigu
    Bonjour à tous,
    J'aimerai savoir s'il est possible de créer des tableaux dynamiques contigus en C ?
    généralement je fais ceci pour créer dynamiquement mes tableaux, mais malheureusement l'espace mémoire réservé n'est pas contigu.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
     
      tab=malloc(nrow*sizeof(double*)); assert(tab!=NULL);
     for(i=0;i<nrow;++i){tab[i]=malloc(ncol*sizeof(double));assert(tab[i]!=NULL);}

  2. #2
    Membre éprouvé
    Inscrit en
    Juin 2008
    Messages
    91
    Détails du profil
    Informations forums :
    Inscription : Juin 2008
    Messages : 91
    Par défaut
    Bonjour,

    La norme C99 ne garantit pas que des appels successifs des fonctions d'allocation (malloc, calloc ou realloc) engendre un espace contigu.

    7.20.3 Memory management functions :
    The order and contiguity of storage allocated by successive calls to the calloc, malloc, and realloc functions is unspecified.
    Après un peu de ruse pourrait faire l'affaire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    int ** pp = malloc( nRow * nCol * sizeof **pp );

  3. #3
    Expert confirmé
    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
    Par défaut
    Pour compléter ce que dit uknow, il faut allouer en une seule fois et placer les adresses correctement dans le tableau de pointeurs :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
      tab=malloc(nrow*sizeof(double*)); assert(tab!=NULL);
      tab[0] = malloc(nrow*ncol*sizeof(double)); assert(tab[0]!=NULL);
      for(i=1;i<nrow;++i) tab[i] = tab[i-1]+ncol;

  4. #4
    Membre Expert 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
    Par défaut
    Une autre solution est d'aplatir ton tableau :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    double* tab=malloc(nrow * ncol *sizeof double);
    for(int i=0; i < nrow; ++i)
      for(int j=0; j < ncol; ++j)
        tab[i*ncol + j] = 0.0;
    Sinon il ne faut pas faire d'assert après un malloc, c'est illogique... Si un malloc foire, ça ne veut pas dire qu'il y a une erreur de programmation ou qu'on viole quoi que ce soit mais simplement qu'il n'y plus de mémoire... D'autant plus qu'en mode release, les assert sont désactivé, donc si malloc foire chez un client ça lui fera une belle segfault

  5. #5
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 026
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 026
    Par défaut
    Citation Envoyé par uknow Voir le message
    Bonjour,

    La norme C99 ne garantit pas que des appels successifs des fonctions d'allocation (malloc, calloc ou realloc) engendre un espace contigu.



    Après un peu de ruse pourrait faire l'affaire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    int ** pp = malloc( nRow * nCol * sizeof **pp );
    Il faut vraiment utiliser la solution de Diogene ou de Trademark car celle-ci est fausse.


    Tu va allouer un tableau de int * faisant k*la taille d'un int.
    Déjà, simple logique, même si cela marcherais, comment veux-tu que le programme sache combien fait une colonne ou combien fait une ligne ?

    Dès que tu va vouloir utiliser ce tableau :

    pp[4][2];est équivalant à *(*(pp + 4) + 2); OR :

    pp + 4est pointeur sur le cinquième élément de ton tableau

    *(pp + 4) est le 5 ème élément de ton tableau qui est un pointeur d'int au contenu indéterminé

    *(pp + 4) + 2 pointeur vers le 2ème élément du tableau pointé par *(pp + 4) c'est à dire un pointeur sur n'importe où dans la mémoire vu que *(pp + 4) est indéterminé

    Donc *(*(pp + 4)+2) est un int qui est on ne sait où. Dès que tu feras une affectation, tu va toucher à de la mémoire qui ne t'appartient pas et tu risque la SEGFAULT



    Pour éviter ce genre d'erreur, j'ai l'habitude de faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    ptr = (T *)malloc(k * sizeof(T));
    Avec k le nombre d'élément et T le type d'élément contenu. Le contenu de la parenthèse gauche doit être identique à celle de la parenthèse droite sauf qu'on lui rajoute un '*'. Si il y une erreur, le compilateur crise.

  6. #6
    Membre éclairé
    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    421
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2011
    Messages : 421
    Par défaut
    En fait, j'avais pensé à ta solution Trademark mais j'avais lu que le faite de faire une multiplication à chaque fois qu'il faut accéder à un élément du tableaux c'était coûteux qu'il faut privilégié l'accès par pointeur.
    Tu as une solution à me proposer pour remplacer les assert ?

  7. #7
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 026
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 026
    Par défaut
    Si tu veux vraiment vérifier le code de retour du malloc tu peux faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    tab=malloc(nrow*sizeof(double*));
    if(tab == NULL)
    {
            printf("...."); exit 1; //si l'erreur empêche ton programme d'atteindre son but premier
            return ...; //sinon tu renvois un code d'erreur que tu gèreras lors de l'appel de ta fonction.
    }
    Ainsi avec le return, après l'appel de ta fonction, tu pourras choisir entre afficher un message d'erreur, sortir proprement (en sauvegardant certains paramètre), exécuter une fonction alternative, cacher l'erreur.

    Je plaisante en disant de cacher l'erreur, mais c'est une pratique qui est malheureusement un peu trop répandue...

  8. #8
    Membre Expert 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
    Par défaut
    Comme le dit Neckara, tu peux vérifier le retour du malloc et afficher un message puis quitter. Généralement, quand un malloc échoue, tu ne pourras pas faire grand chose si ce n'est libérer de la mémoire autre part ou abandonner l'opération en cours pour faire autre chose... Ce qui n'est pas toujours possible.

    j'avais lu que le faite de faire une multiplication à chaque fois qu'il faut accéder à un élément du tableaux c'était coûteux qu'il faut privilégié l'accès par pointeur.
    Non ce n'est pas plus couteux, quelle est la différence entre faire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    tab[i] = tab[i-1]+ncol;
    une soustraction et une addition.

    Et une multiplication et une addition... Franchement c'est des micro-optimisations complétement inutiles. Il vaut mieux allouer UNE fois un bloc de mémoire pour qu'il soit contigus et faire une multiplication en plus, que allouer plusieurs fois un bloc.

    Tu parles d'opération sur les pointeurs, mais il faut bien garder à l'esprit qu'un pointeur c'est un entier sur 8 octets, donc ça ne change pas grand chose...

    Si tu veux aller au fond des choses, je te conseille de lire :cpumemory.pdf.

Discussions similaires

  1. Réponses: 4
    Dernier message: 19/03/2015, 18h31
  2. récupérer la memoire et tableau dynamique
    Par Guigui_ dans le forum Langage
    Réponses: 6
    Dernier message: 06/01/2003, 08h02
  3. AFFICHER UN TABLEAU DYNAMIQUE
    Par ghassenus dans le forum Langage
    Réponses: 2
    Dernier message: 28/12/2002, 14h19
  4. [Kylix] tableau dynamique
    Par sdoura2 dans le forum EDI
    Réponses: 1
    Dernier message: 31/10/2002, 08h57
  5. Réponses: 4
    Dernier message: 13/05/2002, 16h43

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