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 :

Matrice allouée dynamiquement contenant des pointeurs vers structures.


Sujet :

C

  1. #1
    Membre à l'essai
    Homme Profil pro
    Développeur décisionnel
    Inscrit en
    Décembre 2018
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Seine et Marne (Île de France)

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

    Informations forums :
    Inscription : Décembre 2018
    Messages : 8
    Points : 10
    Points
    10
    Par défaut Matrice allouée dynamiquement contenant des pointeurs vers structures.
    Bonjour à toutes et tous,

    J'ai écrit une petite fonction permettant d'allouer la mémoire nécessaire pour une matrice de dimensions dim_i et dim_j. Cette matrice contient des doubles.
    Cependant, je voudrais que cette matrice puisse contenir des pointeurs vers une structure "S", mais je galère niveau syntaxe. Comment faut-il changer cette fonction pour arriver à mes fins ?

    Merci beaucoup par avance à quiconque pourra m'aider !

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    double** Allocate_Matrix(int dim_i, int dim_j){
      int i = 0, j = 0;
      double** mat = NULL;
     
      mat = (double**) malloc(dim_i*sizeof(double*));
      if (mat == NULL) exit(EXIT_FAILURE);
      for (i = 0; i < dim_i; i++){
        mat[i] = (double*)malloc(dim_j*sizeof(double));
        if (mat[i] == NULL){
          for (i = i-1; i = 0; i--) free(mat[i]);
        }
      }
      return mat;
    }

  2. #2
    Expert éminent sénior
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 630
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 630
    Points : 10 556
    Points
    10 556
    Par défaut
    Et un truc comme cela ?


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
        t_S** mat_S;
     
        mat_S = malloc(dim_i * dim_j * sizeof(t_S*));
        if (mat_S != NULL) { memset(mat_S, 0, (dim_i * dim_j * sizeof(t_S*))); }

  3. #3
    Membre à l'essai
    Homme Profil pro
    Développeur décisionnel
    Inscrit en
    Décembre 2018
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Seine et Marne (Île de France)

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

    Informations forums :
    Inscription : Décembre 2018
    Messages : 8
    Points : 10
    Points
    10
    Par défaut
    Impeccable, merci !

  4. #4
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 689
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 689
    Points : 30 983
    Points
    30 983
    Billets dans le blog
    1
    Par défaut
    Bonjour
    Citation Envoyé par foetus Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
        t_S** mat_S;
        mat_S = malloc(dim_i * dim_j * sizeof(t_S*));
        if (mat_S != NULL) { memset(mat_S, 0, (dim_i * dim_j * sizeof(t_S*))); }
    Il me semble que tu as transformé la nature intrinsèque de sa matrice non ? Il avait une matrice 2D et tu lui donnes une matrice 1D. Alors que d'après ce que j'ai compris, il avait un échiquier de doubles et il voulait un échiquier de pointeurs.
    Mais bon, si ça lui convient...

    Citation Envoyé par Oblivion0 Voir le message
    Impeccable, merci !
    Attention, dans ton premier code tu sors du programme si malloc échoue ce qui n'est pas super propre. Généralement, si une fonction ne peut pas faire son travail, on lui fait retourner une valeur spéciale et c'est l'appelant qui gère.
    De même si les sous-malloc échouent tu libères ce qui a été alloué (bon réflexes !) mais il faut aussi indiquer le souci à l'appelant...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  5. #5
    Invité
    Invité(e)
    Par défaut
    Bonjour,

    Cette condition est à revoir :
    Citation Envoyé par Oblivion0 Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    for (i = i-1; i = 0; i--) free(mat[i]);

  6. #6
    Expert éminent sénior
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 630
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 630
    Points : 10 556
    Points
    10 556
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    Il me semble que tu as transformé la nature intrinsèque de sa matrice non ? Il avait une matrice 2D et tu lui donnes une matrice 1D. Alors que d'après ce que j'ai compris, il avait un échiquier de doubles et il voulait un échiquier de pointeurs.
    Mais bon, si ça lui convient...
    Tu as entièrement raison
    Mais est-bien utile de faire un tableau de tableaux (ce qu'est une matrice) ?

    Tout est plus lourd : les allocations ligne par ligne, les désallocations et avoir un niveau pointeur en + (une variable de type t_S*** contre de type t_S**)
    Non ici , je pense qu'il faut mieux coder une interface matrice (avec un type fixe), avec les constructeurs, les destructeurs et les mutateurs qui vont bien.

  7. #7
    Membre à l'essai
    Homme Profil pro
    Développeur décisionnel
    Inscrit en
    Décembre 2018
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Seine et Marne (Île de France)

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

    Informations forums :
    Inscription : Décembre 2018
    Messages : 8
    Points : 10
    Points
    10
    Par défaut
    Citation Envoyé par Winjerome Voir le message
    Cette condition est à revoir :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    for (i = i-1; i = 0; i--) free(mat[i]);
    En quoi est-ce faux ?

  8. #8
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    Ce code fait rien. Tu initialises i, mais osef vu que tu lui assignes directement 0, et 0 c'est évalué à faux donc on rentre jamais dans la boucle.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  9. #9
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 689
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 689
    Points : 30 983
    Points
    30 983
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Oblivion0 Voir le message
    En quoi est-ce faux ?
    for(initialisation; condition; increment).
    Déjà dans la condition tu as confondu "comparaison" et "affectation" (i == 0 et non i = 0). Nota: si tu crains de te tromper à l'avenir, alors inverse les deux opérandes. Tu aurais écrit 0 = i le compilo aurait gueulé sa race alors qu'écrire 0 == i fonctionnera tout comme i == 0.
    Et ensuite la condition est une condition de continuation, pas une condition d'arrêt. Tu dois demander tant que i supérieur à 0 parce que c'est la condition qui continue la boucle ; et non pas demander i vaut 0 en espérant que le compilo comprendra que tu indiques une condition qui permet de quitter la boucle.
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  10. #10
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Salut,
    Citation Envoyé par Sve@r Voir le message
    Bonjour

    Il me semble que tu as transformé la nature intrinsèque de sa matrice non ? Il avait une matrice 2D et tu lui donnes une matrice 1D. Alors que d'après ce que j'ai compris, il avait un échiquier de doubles et il voulait un échiquier de pointeurs.
    De manière générale, le but d'une matrice reste toujours, de permettre la représentation d'un nombre d'éléments équivalent au multiple de l'ensemble de ses dimensions.

    Pour prendre un exemple concret : si tu veux créer une matrice 2D composée de L lignes et de C colonnes, ton objectif final reste, a priori, de pouvoir représenter L x C éléments, et ce, quel que soit le type des éléments que l'on veut représenter, non .

    Dés lors, quelle serait la différence entre le code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    double ** mat;
    mat = malloc(sizeof(double*)* MAXLINES);
    for(int i=0; i< MAXLINES; i++)
        mat[i]= malloc(sizeof(double) * MAXCOLS);
    qui finirait bel et bien par allouer l'espace mémoire correspondant à MAXLINES * MAXCOLS et le code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    double * mat;
    mat = malloc(sizeof(double) MAXLINES * MAXCOLS);
    qui produira le même effet, à ceci près que
    1. l'espace mémoire est alloué en une seule fois
    2. nous "économisons" l'usage d'un pointeur
    3. les accès se font à l'aide d'un indice (mat[ligne * MAXCOLS + colonne]) au lieu de deux (mat[ligne][colonne])

    Hé bien la réponse est toute simple : dans le pire des cas, cela reviendra strictement au même (avec le léger avantage de pouvoir travailler sur un pointeur au lieu de devoir travailler sur un pointeur de pointeur).

    Dans le meilleur des cas comme il n'y a aucune garantie que les allocations successives effectuées lors de la boucle soient effectivement contiguës en mémoire, il n'est même pas interdit de penser que la contiguité des données nous permettra de profiter avantageusement des éventuels système de cache utilisés par le processeur.

    Alors, bien sur, au final, cela nous oblige à une petite gymnastique mentale pour calculer l'indice de l'élément auquel on souhaite accéder (à l'aide de la formule indice = ligne_demandée * nombre_de_colonne + colonne_demandée). Mais n'est ce pas un bien faible prix à payer pour la simplification des prototypes que cela nous autorise

    Tu as le droit d'avoir ton propre avis sur le sujet, mais, étant plus habitué au C++ qu'au C, je trouve personnellement que ca vaut la peine
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  11. #11
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 689
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 689
    Points : 30 983
    Points
    30 983
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par koala01 Voir le message
    les accès se font à l'aide d'un indice (mat[ligne * MAXCOLS + colonne]) au lieu de deux (mat[ligne][colonne])
    Là c'est un point important car tu dois donc reprendre tout ton code pour réécrire tes accès. C'était un peu le but de ma remarque initiale. Je ne critiquais pas la transformation elle-même, juste le fait qu'elle n'ait pas été mentionnée par foetus car ça implique une refonte par le PO

    Citation Envoyé par koala01 Voir le message
    Dans le meilleur des cas comme il n'y a aucune garantie que les allocations successives effectuées lors de la boucle soient effectivement contiguës en mémoire
    En fait, dans les allocations en 2D, c'est garanti qu'elles ne seront pas contigües en mémoire. La première alloue n pointeurs tous contigus (donc par exemple 1000, 1001, 1002, 1003 etc). Il est donc obligé qu'aucune ligne ne pourra être allouée en 1000, 1001, 1002 etc.

    Citation Envoyé par koala01 Voir le message
    Alors, bien sur, au final, cela nous oblige à une petite gymnastique mentale pour calculer l'indice de l'élément auquel on souhaite accéder (à l'aide de la formule indice = ligne_demandée * nombre_de_colonne + colonne_demandée). Mais n'est ce pas un bien faible prix à payer pour la simplification des prototypes que cela nous autorise
    N'oublie pas aussi qu'on peut avoir besoin de convertir un indice en ligne/colonne => ligne=i/MAXCOLS et colonne=i%MAXCOLS
    Citation Envoyé par koala01 Voir le message
    Tu as le droit d'avoir ton propre avis sur le sujet,
    Oui, c'est d'ailleurs un truc que je dis assez souvent.
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  12. #12
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    Là c'est un point important car tu dois donc reprendre tout ton code pour réécrire tes accès.
    tu dois reprendre le code ... existant Le nouveau code ne posera aucun problème, et, comme les problèmes de création et d'allocation sont, de manière générale, les premiers résolus, on peut espérer que cet aspect reste assez limité, malgré tout
    C'était un peu le but de ma remarque initiale. Je ne critiquais pas la transformation elle-même, juste le fait qu'elle n'ait pas été mentionnée par foetus car ça implique une refonte par le PO
    Sur ce point, par contre, je suis tout à fait d'accord avec toi


    En fait, dans les allocations en 2D, c'est garanti qu'elles ne seront pas contigües en mémoire. La première alloue n pointeurs tous contigus (donc par exemple 1000, 1001, 1002, 1003 etc). Il est donc obligé qu'aucune ligne ne pourra être allouée en 1000, 1001, 1002 etc.
    Tu as raison de chicaner sur ce point, car je me suis effectivement mal exprimé :

    Ce que je voulais dire, c'est que, chaque ligne se voyant allouer un espace mémoire de taille identique (mettons pour la facilité, 10 bytes), on n'a aucune garantie que le début de l'espace mémoire alloué à une ligne particulière soit effectivement contigu à l'adresse mémoire à laquelle se trouve la dernière donnée de la ligne précédante, et que nous ayons donc une représentation proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    ligne 0 : 1000 à 1009 inclus
    ligne 1 : 1010 à 1019 inclus
    ligne 2 : 1020 à 1029 inclus
    ligne 3 : 1030 à 1039 inclus
    Ca peut arriver, à titre plus ou moins exceptionnel, et ce serait l'idéal pour les mécanisme de cache, mais, a priori, il est beaucoup plus vraisemblable de penser que cela n'arrivera pas
    N'oublie pas aussi qu'on peut avoir besoin de convertir un indice en ligne/colonne => ligne=i/MAXCOLS et colonne=i%MAXCOLS
    Bien sur
    Oui, c'est d'ailleurs un truc que je dis assez souvent.
    Donc, tu essayais juste de tirer la discussion en longueur en jouant l'avocat du diable

    Ca ne me dérange pas du tout, car je le fais aussi régulièrement. Ca permet de faire sortir des notions qu'on a trop souvent tendance à oublier ou à mal comprendre
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Initialiser une structure contenant des pointeurs ?
    Par Silvano_Dimitrio dans le forum C++
    Réponses: 5
    Dernier message: 27/01/2019, 00h43
  2. Réponses: 31
    Dernier message: 19/09/2011, 10h37
  3. Réponses: 4
    Dernier message: 23/03/2007, 09h40
  4. Réponses: 2
    Dernier message: 21/03/2007, 10h55
  5. [C#]Pointeur vers structure
    Par torNAdE dans le forum Windows Forms
    Réponses: 3
    Dernier message: 08/05/2006, 19h43

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