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 a taille variable


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre chevronné
    Profil pro
    Inscrit en
    Septembre 2009
    Messages
    1 854
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2009
    Messages : 1 854
    Par défaut tableau a taille variable
    Bonjour,

    voici mon code :
    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
    typedef struct _ENUMLIST_ELMT {
    	INT32 val;				// valeur de l'enum
    	UINT8 str[];			// pointeur sur la chaine de caractère associée
    } ENUMLIST_ELMT;
     
     
    typedef struct _ENUMLIST {
    	INT32 size;
    	ENUMLIST_ELMT listEnum[];
    } ENUMLIST;
     
     
    ENUMLIST enumList1 = {
    	.size = 3,
     
    	.listEnum = {
    		{.val = 0, .str = "non"},
    		{.val = 1, .str = "oui"},
    		{.val = 2, .str = "je sais pas :("}
    	}
    };
    pouvez-vous me dire si ce code est vraiment bon : ça compile sans erreur mais j'ai quand même quelques doutes.
    Est-ce qu'en faisant ça, tous les éléments se suivent vraiment ?

  2. #2
    Membre chevronné
    Profil pro
    Inscrit en
    Septembre 2009
    Messages
    1 854
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2009
    Messages : 1 854
    Par défaut
    je viens de tester mon code et il ne fonctionnait pas, il a fallu que je modifie la structure suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    typedef struct _ENUMLIST_ELMT {
    	INT32 val;				// valeur de l'enum
    	UINT8 *str;			        // pointeur sur la chaine de caractère associée
    } ENUMLIST_ELMT;
    Avant, sizeof(ENUMLIST) valait 4 (maintenant 8) => donc l'initialisation n'étatit pas bonne



    voici la fonction que j'utilise
    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
    // récupère l'adresse de la chaine qui correspond à la valeur de l'enum
    // enumVal : valeur de l'enum à rechercher
    // list : list de pointeur contenant tous les enums gérés (=> chaines de caractères associés)
    ROM UINT8* getEnumString(INT32 enumVal, ROM ENUMLIST *list){
    	static ROM UINT8 strErr[] = "not found";
    	UINT32 i;
     
    	ROM ENUMLIST_ELMT *listEnum;
     
    	printf("list(value: %ld): .addr=%p, .size:%ld\r\n", enumVal, list, list->size);
    	printf("\tsizeof(*list): %ld, sizeof(ENUMLIST_ELMT): %ld\r\n", sizeof(*list), sizeof(ROM ENUMLIST_ELMT));
     
    	for(i=0; i<list->size; i++){
     
    		listEnum = &(list->listEnum[i]); // list->listEnum est un tableau d'elements de type ENUMLIST_ELMT
     
     
    		if (listEnum->val == enumVal){
    			printf("\t[OK]addr enum: %p, val: %ld, addr string: %p, val string: %s\r\n", listEnum, listEnum->val, listEnum->str, listEnum->str);
    			return listEnum->str;
     
    		} else if (listEnum->val > enumVal){
    			printf("\t[ERR]addr enum: %p, val: %ld, addr string: %p, val string: %s\r\n", listEnum, listEnum->val, listEnum->str, listEnum->str);
    			return strErr;
    		}
    		printf("\t[NOK]addr enum: %p, val: %ld, addr string: %p, val string: %s\r\n", listEnum, listEnum->val, listEnum->str, listEnum->str);
    		//listEnum++;
    	}
     
    	printf("\t[ERR]%s => addr: %p\r\n", strErr, strErr);
    	return strErr;	
     
    }
    comment je l'utilise :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    // tableau stocké en ROM
    ROM ENUMLIST enumList1 = {
    	.size = 3,
     
    	.listEnum = {
    		{.val = 0, .str = "non"},
    		{.val = 1, .str = "oui"},
    		{.val = 2, .str = "je sais pas :("}
    	}
    };
     
    printf("sizeof(enumList1): %ld \r\n", sizeof(enumList1)); // vaut 4 => est-ce normal
    printf("chaine: %s\r\n", getEnumString(1, &enumList1);
    => a priori ça fonctionne mais le sizeof(enumList1) ne me renvoi pas la bonne valeur.
    Si le sizeof est faux, il n'y a pas de risques que d'autres variables se trouvent au même emplacement ?

  3. #3
    Invité
    Invité(e)
    Par défaut
    Bonjour,
    Pourquoi n'utilisez-vous les noms de type de base int, char, unsigned etc.
    Je ne connais pas cette syntaxe
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    ROM ENUMLIST enumList1 = {
    	.size = 3,
     
    	.listEnum = {
    		{.val = 0, .str = "non"},
    		{.val = 1, .str = "oui"},
    		{.val = 2, .str = "je sais pas :("}
    	}
    };

  4. #4
    Membre chevronné
    Profil pro
    Inscrit en
    Septembre 2009
    Messages
    1 854
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2009
    Messages : 1 854
    Par défaut
    Citation Envoyé par Pierre Dolez Voir le message
    Bonjour,
    Pourquoi n'utilisez-vous les noms de type de base int, char, unsigned etc.
    Pour que mon code soit plus facilement portable : la taille des types du C n'ont pas une valeur fixe => en faisant ça je suis sure de la taille de mes variables



    Citation Envoyé par Pierre Dolez Voir le message
    Je ne connais pas cette syntaxe
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    ROM ENUMLIST enumList1 = {
    	.size = 3,
     
    	.listEnum = {
    		{.val = 0, .str = "non"},
    		{.val = 1, .str = "oui"},
    		{.val = 2, .str = "je sais pas :("}
    	}
    };
    ça équivaut a initialiser la variable comme ceci (à par que le valeurs sont affectées à la création de la variable) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    enumList1.size = 3;
     
    enumList1.listEnum[0].val = 0;
    enumList1.listEnum[0].str = "non";
     
    enumList1.listEnum[1].val = 0;
    enumList1.listEnum[1].str = "oui";
     
    enumList1.listEnum[2].val = 0;
    enumList1.listEnum[0].str = "je sais pas :(";
    => c'est très utile pour avoir un structure avec des valeurs par défaut. Par contre là où j'ai un doute c'est sur la déclaration du tableau sans taille définie : j'ai testé mon programme et ça à l'air de fonctionner (à part que le sizeof() est faux => donc problème si on veut faire des incrémentations de pointeur sur ce type de variable : mais je peux quand même déterminer la taille grâce à la variable .size)


    J'utilise ce système pour afficher du texte en fonction d'une valeur donnée :
    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
     
    // **************************
    // fichier mes_enums.h
    extern ROM ENUMLIST enumList1
    extern ROM ENUMLIST enumList2
    // ...
     
    // **************************
    // fichier mes_enums.c
    ROM ENUMLIST enumList1 = {
    	.size = 3,
     
    	.listEnum = {
    		{.val = 0, .str = "non"},
    		{.val = 1, .str = "oui"},
    		{.val = 2, .str = "je sais pas :("}
    	}
    };
     
    ROM ENUMLIST enumList2 = {
    	.size = 2,
     
    	.listEnum = {
    		{.val = 5, .str = "aille"},
    		{.val = 10, .str = "ouille"}
    	}
    };
     
    // ...
     
    // **************************
    // dans mon main.c
     
    printf("%s\r\n", getEnumString(10, &enumList2));
    => avec ce système, je peux déclarer facilement de nouvelles énumérations en utilisant un minimum de ressources (RAM/ROM) => je programme sur un µControlleur...peut-etre qu'il existe une meilleure méthode...

  5. #5
    Invité
    Invité(e)
    Par défaut
    Oui, mais je ne suis pas sûr que ce code soit du C standard. Donc, sur ce point je ne m'aventurerai pas plus.
    Pour initialiser un enum il y a les méthodes standard qui fonctionnent très bien.

    Par contre sur le problème de dimension de tableau, les machines sont très bêtes, surtout la mienne, et si vous lui dites de travailler avec un tableau, il faut lui dire la taille du tableau.
    Il y a plusieurs façons de "réserver de l'espace dans la mémoire pour y mettre un tableau", mais à mon avis, la meilleure méthode est encore malloc et ses copines calloc realloc.

    J'avoue ne pas connaître µControlleur, mais à mon avis ce n'est pas vraiment du C.

  6. #6
    Membre chevronné
    Profil pro
    Inscrit en
    Septembre 2009
    Messages
    1 854
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2009
    Messages : 1 854
    Par défaut
    Citation Envoyé par Pierre Dolez Voir le message
    J'avoue ne pas connaître µControlleur, mais à mon avis ce n'est pas vraiment du C.
    => on prorgamme pareil qe sur PC a part que le nombre de libraries standard incluse avec le compilo est très limité, qu'il faut faire gaffe à la consommation de RAM/ROM (=> donc éviter les malloc pour ne pas avoir de mauvaises surprises).


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    En C99, il n'est pas valide d'initialiser un tel tableau.
    Bon ben là c'est clair, faut que je trouve une autre solution...


    merci

  7. #7
    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
    => a priori ça fonctionne mais le sizeof(enumList1) ne me renvoi pas la bonne valeur.
    Si le sizeof est faux, il n'y a pas de risques que d'autres variables se trouvent au même emplacement ?
    A ma connaissance, l'initialisation d'un 'flexible array' n'est pas conforme au standard C99 mais est une extension donnée par certains compilateurs pour des variables statiques. En C99, il n'est pas valide d'initialiser un tel tableau.

    Il n'est pas étonnant que le sizeof ne donne pas dans ce cas la taille réelle de la mémoire allouée à l'objet ce qui ne serait pas conforme au standard pour lequel le 'flexible array' n'a pas de mémoire allouée. Toutefois, sa présence peut changer le résultat du sizeof en modifiant le nombre de bytes de padding de la structure.

  8. #8
    Membre averti
    Profil pro
    Inscrit en
    Août 2010
    Messages
    38
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2010
    Messages : 38
    Par défaut
    Citation Envoyé par diogene Voir le message
    A ma connaissance, l'initialisation d'un 'flexible array' n'est pas conforme au standard C99 mais est une extension donnée par certains compilateurs pour des variables statiques. En C99, il n'est pas valide d'initialiser un tel tableau.

    Il n'est pas étonnant que le sizeof ne donne pas dans ce cas la taille réelle de la mémoire allouée à l'objet ce qui ne serait pas conforme au standard pour lequel le 'flexible array' n'a pas de mémoire allouée. Toutefois, sa présence peut changer le résultat du sizeof en modifiant le nombre de bytes de padding de la structure.
    Si c'est dans la norme C99, ils appellent ça VLA pour "variable length array":
    http://www.open-std.org/jtc1/sc22/wg14/www/standards/
    ( lien direct: http://www.open-std.org/jtc1/sc22/wg...docs/n1256.pdf )

    Voir la partie 7.5.2 (un bon exemple est donné en page 130 sur la dernière révision de la norme, qui d'ailleurs est numérotée 118 !).

    Mais il est important de savoir que la mémoire est allouée sur la pile, ça doit donc rester cantonné à l'intérieur des fonctions.

    Sinon un bon résumé en français:
    http://nicolasj.developpez.com/articles/c99/

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

Discussions similaires

  1. sommes des cases d'un tableau de taille variable
    Par Bubale dans le forum Macros et VBA Excel
    Réponses: 2
    Dernier message: 18/04/2008, 00h18
  2. Sélectionner tableau a taille variable
    Par Iloon dans le forum Macros et VBA Excel
    Réponses: 6
    Dernier message: 07/02/2008, 16h20
  3. [Conception] tableau de taille variable
    Par salirose dans le forum PHP & Base de données
    Réponses: 16
    Dernier message: 21/10/2006, 13h53
  4. Réponses: 1
    Dernier message: 14/09/2006, 10h53
  5. [TP] Tableau de taille variable
    Par Ripley dans le forum Turbo Pascal
    Réponses: 4
    Dernier message: 30/01/2006, 15h36

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