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 :

Taille tableau dynamique


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éprouvé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2011
    Messages
    756
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Août 2011
    Messages : 756
    Par défaut Taille tableau dynamique
    Salutation,

    désolé pour la question basique mais cela fait tellement longtemps que je n'ai pas touché au C que je ne sais plus trop comment m'y prendre. Je me suis un peu trop habitué au size et length de java

    Je possède une structure

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    typedef struct frequence_element{
     int element;
     int frequence;
     
    }frequence_element;
    J'ai à coté une fonction qui va me renvoyer un tableau de cette structure

    Le prototype est donc

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    frequence_element* init()
    Après l'appel de ma fonction comment pourrais-je retrouver la taille de mon tableau de frequence élément ?

    En fait, lorsque j'alloue mon tableau, je lui alloue une taille donné; mais en réalité cela ne représente que le nombre total et non le nombre effectif de ma taille du tableau.

    J'aimerais donc pouvoir récupérer cette taille réelle pour éviter d'aller lire des tours de boucles inutiles..

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    frequence_element* tab=malloc(taille*sizeof(frequence_element));//déclaré dans init() taille représente le max que je connais dans le main et non le nb effectif de valeur réelle
    Merci pour votre aide !

  2. #2
    Membre Expert
    Avatar de Pyramidev
    Homme Profil pro
    Tech Lead
    Inscrit en
    Avril 2016
    Messages
    1 513
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Tech Lead

    Informations forums :
    Inscription : Avril 2016
    Messages : 1 513
    Par défaut
    Bonjour,

    Voici ce que dit la FAQ du langage C :
    « Il n'existe pas en C de fonction permettant de connaître la taille d'un tableau alloué dynamiquement, il faut donc impérativement conserver la taille de chaque tableau alloué. Une implémentation particulière peut cependant fournir une fonction permettant d'obtenir cette information (la fonction _msize sous Windows par exemple). »

    Lien : http://c.developpez.com/faq/?page=L-...leau-dynamique

  3. #3
    Membre éprouvé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2011
    Messages
    756
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Août 2011
    Messages : 756
    Par défaut
    Ah zut, bon au moins ça explique pourquoi je ne m'en rappelais pas


    C'est pas très grave au pire, je peux toujours créer une seconde structure artificielle qui va stocker mon tableau + sa taille.
    Sa revient à contourner le problème, mais je vois pas très bien comment faire autrement.

    Merci.

  4. #4
    Expert confirmé
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 768
    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 768
    Par défaut
    Citation Envoyé par Amnael Voir le message
    une seconde structure artificielle qui va stocker mon tableau + sa taille.
    Et oui et en plus il te manque peut-être une capacité: parce que si tu fais un tableau vraiment dynamique (éventuellement avec realloc) il faut stocker le nombre d’éléments (sa taille ou nombre d'éléments) et son nombre maximal d'éléments (sa capacité)

  5. #5
    Membre Expert
    Inscrit en
    Mars 2005
    Messages
    1 431
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 1 431
    Par défaut
    Exemple d'implémentation considérant ce qui a été écrit plus haut, avec un flexible array member :

    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
    #include <stdlib.h>
     
    #define ATYPE char
     
    typedef struct {
        size_t capacity,
               size;
        ATYPE data[];
    } array_t;
     
    array_t *array_alloc(size_t reserve) {
        array_t *a = malloc(sizeof(array_t) + reserve * sizeof(ATYPE));
        if (a) {
            a->capacity = reserve;
            a->size = 0;
        }
        return a;
    }

    Citation Envoyé par Amnael Voir le message
    C'est pas très grave au pire, je peux toujours créer une seconde structure artificielle qui va stocker mon tableau + sa taille.
    Sa revient à contourner le problème, mais je vois pas très bien comment faire autrement.
    Tu sais, c'est aussi ce que fait Java.

  6. #6
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 835
    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 835
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Amnael Voir le message
    C'est pas très grave au pire, je peux toujours créer une seconde structure artificielle qui va stocker mon tableau + sa taille.
    Bonjour

    Ce n'est pas une structure artificielle, c'est une vraie structure permettant de répondre proprement à un problème. C'est d'ailleurs ce que je fais tout le temps chaque fois que je veux gérer un truc "grossissant"

    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
    typedef struct {
        truc* data;
        truc* new;
        size_t nb_elem;
        size_t sz_alloc;
    } t_dynamictab;
     
    t_dynamictab tableau;
    tableau.data=NULL;
    tableau.nb_elem=0;
    tableau.sz_alloc=0;
     
    while (recuperation_info())
    {
        // Si on a atteitn la limite allouée (ce qui arrive à la toute première itération puisque tout est à 0)
        if (tableau.nb_elem == tableau.sz_alloc)
        {
            // On agrandit la taille
            tableau.sz_alloc+=SIZE;
     
            // On réalloue de la mémoire (si la zone à réallouer est à "NULL", la réallocation se comporte comme une allocation)
            tableau.new=realloc(tableau.data, tableau.sz_alloc * sizeof(truc));
     
            // On vérifie le résultat de la réallocation
            if (tableau.new == NULL)
            {
                  // Pb d'allocation à gérer - Généralement libérer la mémoire déjà allouée et sortir de l'algo
                  ....
            }
     
            // La réallocaton a réussi - On récupère la zone allouée
            tableau.data=tableau.new;
        }
     
        // Ici on est certain d'avoir assez de place pour stocker l'info récupérée
        tableau.data[tableau.nb_elem]=info;
     
        // On a un élément de plus
        tableau.nb_info++;
    }


    Citation Envoyé par Amnael Voir le message
    Sa revient à contourner le problème,
    Non, ça revient à répondre au problème

    Citation Envoyé par Amnael Voir le message
    mais je vois pas très bien comment faire autrement..
    Ben peut-être parce qu'il n'y a pas d'autre solution...
    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]

  7. #7
    Membre éprouvé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2011
    Messages
    756
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Août 2011
    Messages : 756
    Par défaut
    Toujours aussi fan de tes réponses depuis math forum Sve@r

    La question est donc résolu, merci à tous.


    Pour rebondir sur un point tout de même...comment peut-on savoir qu'une solution qu'on met en place règle un problème et ne fait pas que le masquer ?

    Dans tous les cas finalement je vois que ça vaudrait le coup que je me fasse une petite librairie C pour régler ces problèmes de tableaux dynamique, quitte à justement implémenter manuellement certaines fonctions existant en java pour retourner les tailles justement.

    Existe t-il en C le concept de généricité (pas sûr d'employer le bon terme là). J'entends par là réaliser une fonction ou une structure qui ne prendrait pas un type précis en paramètres (int, char etc etc); mais un type plus large, qui serait déterminé par la suite par les opération appliqué.

    Exemple typique d'Ocaml où on a des types définis par 'a 'b etc etc qui peuvent ensuite prendre n'importe quel type.

  8. #8
    Membre Expert
    Inscrit en
    Mars 2005
    Messages
    1 431
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 1 431
    Par défaut
    Il faut recourir au préprocesseur pour faire de la programmation générique en C, et je te préviens de suite : c'est ni vraiment type-safe, ni vraiment sexy.

    Ce que tu peux faire en premier lieu, par exemple, c'est écrire le code avec un nom de type générique (comme je l'ai fait dans mon exemple plus haut), placer le code dans array_generic.h et array_generic.impl (une sorte de .c générique) puis le spécialiser dans un couple .h / .c dédié :

    Code array_int.h : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    #define ATYPE int
      #include "array_generic.h"
    #undef ATYPE

    Code array_int.c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    #define ATYPE int
      #include "array_generic.h"
      #include "array_generic.impl"
    #undef ATYPE

    Il est possible ensuite de perfectionner le truc en adaptant les identifiants (de types et fonctions) au type paramètre ou même de générer du code en fonction du type paramètre. Jette un oeil à la concaténation au sein des macros et à la macro _Generic.

  9. #9
    Membre Expert
    Homme Profil pro
    sans emploi
    Inscrit en
    Janvier 2014
    Messages
    539
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : sans emploi
    Secteur : Conseil

    Informations forums :
    Inscription : Janvier 2014
    Messages : 539
    Par défaut
    Bonjour,

    Citation Envoyé par Amnael Voir le message
    [...]
    Pour rebondir sur un point tout de même...comment peut-on savoir qu'une solution qu'on met en place règle un problème et ne fait pas que le masquer ?
    Parce qu'il y a problèmes et problèmes. Il y a les problèmes qu'on résout simplement comme «je dois écrire une fonction qui me donne les nombres de fibonacci», là il y a plusieurs solutions plus ou moins efficaces. Il y a aussi les problèmes qui surviennent et qu'on essaye de résoudre ou de contourner comme par exemple «ma fonction fibo explose la pile», on la résout en changeant d'algo ou on la contourne en augmentant la taille de la pile. Il y a aussi les problèmes qu'on a pu su voir venir, «arg, je dois manipuler de très grands nombres avec ma fonction fibo», là on revoit la conception et au choix on utilise une bibliothèque d'arithmétique en précision arbitraire ou on réinvente la roue. Il y a les gros problèmes qu'on contourne par manque de temps, d'expériences ou de rigueur comme «je ne comprends pas pourquoi ça plante avec un tableau de taille 10 mais ça ne plante plus si je mets une taille à 10000».
    Et finalement il y a les problèmes qui n'en sont pas comme «en java je peux avoir directement des tableaux croissant dynamiquement et j'ai un moyen de connaître leur taille, c'est un problème de ne pas pouvoir le faire en C». Ce n'est carrément pas un problème, c'est juste une différence de fonctionnalité.

    Pour info, la solution classique de Svear est plus performante si au lieu d'une croissance linéaire de la capacité on implémente une croissance exponentielle (comme le fait java d'ailleurs). Cela permet de garder les mêmes compléxités temporelles pour les primitives de base.

    Citation Envoyé par Amnael Voir le message
    Dans tous les cas finalement je vois que ça vaudrait le coup que je me fasse une petite librairie C pour régler ces problèmes de tableaux dynamique, quitte à justement implémenter manuellement certaines fonctions existant en java pour retourner les tailles justement.
    De telles bibliothèques tierces existent déjà. Il y a comme la libapr d'Apache, la Glib de GNU, la gnulib au niveau source …

    Citation Envoyé par Amnael Voir le message
    Existe t-il en C le concept de généricité (pas sûr d'employer le bon terme là). J'entends par là réaliser une fonction ou une structure qui ne prendrait pas un type précis en paramètres (int, char etc etc); mais un type plus large, qui serait déterminé par la suite par les opération appliqué.

    Exemple typique d'Ocaml où on a des types définis par 'a 'b etc etc qui peuvent ensuite prendre n'importe quel type.
    Oui et non. Le langage ne fournit pas un mécanisme simple pour ça. Mais tu peux utiliser les mécanismes existant pour le faire quand même, mais comme ce n'était pas prévu «au départ» ça fait toujours un peu usine à gaz et/ou un tonne de code pour ce qui serait plus simplement implémenté dans un autre langage.

    Par exemple pour avoir une sorte de mécanisme d'héritage tu peux le faire avec des structs, tu peux faire ce qui ressemble à des classes aussi → regarde du côté de GObject, la base pour la GLib,GIO, GDK,GTK+.

    Pour ce qui est le polymorphisme tu peux te tourner vers _Generic (C11), elle est utilisée pour implémenter tgmath (type générique math). Le compilateur clang fournit une infrastructure propriétaire pour ça aussi.

    Mais au final, le plus important quand tu fais du C c'est aussi de se mettre à l'esprit C (ok bien qu'ayant évolué depuis 40 ans reste relativement bas niveau par rapport à ce qu'on a pu voir apparaître par la suite).

  10. #10
    Expert confirmé
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 768
    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 768
    Par défaut
    Citation Envoyé par Amnael Voir le message
    Existe t-il en C le concept de généricité (pas sûr d'employer le bon terme là). J'entends par là réaliser une fonction ou une structure qui ne prendrait pas un type précis en paramètres (int, char etc etc); mais un type plus large, qui serait déterminé par la suite par les opération appliqué.
    Attention il faut savoir ce qu'on fait avec un type void*.

    Et avec les P.O.D. (int, char, short, ...) tu ne crées pas de pointeur mais tu mets la valeur directement puisque sizeof(void*) c'est soit 32 soit 64 octets bits.

    Édit: Merci Médinoc Parce que 32 octets cela en fait pour une super précision

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

Discussions similaires

  1. Changer la taille d'un tableau dynamique
    Par clem1313 dans le forum Langage
    Réponses: 1
    Dernier message: 28/02/2006, 01h57
  2. Réponses: 6
    Dernier message: 16/01/2006, 13h29
  3. Comment récupérer la taille d'un tableau dynamique ?
    Par Tchaill39 dans le forum Langage
    Réponses: 4
    Dernier message: 08/12/2005, 14h21
  4. [c++] Tableau avec taille initiale dynamique
    Par mister3957 dans le forum C++
    Réponses: 15
    Dernier message: 22/11/2005, 11h33
  5. Connaitre la taille d'un tableau dynamique
    Par lewellah dans le forum C
    Réponses: 2
    Dernier message: 23/09/2005, 18h37

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