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 :

déclaration de structure


Sujet :

C

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

    Informations forums :
    Inscription : Septembre 2009
    Messages : 1 821
    Points : 979
    Points
    979
    Par défaut déclaration de structure
    Bonjour,

    Je travaille sur un µC, j'ai donc deux zones mémoires pour le stockage de mes données : la ROM et la RAM.

    J'ai des éléments qui sont constitués
    - nom de l'élément : type string
    - description de l'élément : type string
    - pointeur de fonction associé a l'élément


    donc j'ai créé ma structure comme ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    typedef struct _structElement
    {
    	rom char *eltName;
    	rom char *eltDesc;
    	TYPE_FUNC_VOIDVOID *ptr_action;
    } structElement;
    Declaration de mon type pointeur de fonction TYPE_FUNC_VOIDVOID :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    typedef void TYPE_FUNC_VOIDVOID(void); // fonction de type : void toto(void)

    Donc voici comment je déclare un élément :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    rom const structElement elt1 = { "ma commande1"   , "ma description1", toto()};
    rom const structElement elt2 = { "ma commande2"   , "ma description2", tutu()};
    ...
    la liste de tous mes elements :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    rom structElement *rom tabElt[] =  {&elt1, &elt2, ...}

    Donc pour lancer la commande de l'element 0, je fais :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    (*tabElt[0]->ptr_action)();
    => pas encore testé



    Mon but est d'avoir un tableau qui est composé de ma liste de commande et qu'il soit facile de modifier/ajouter un élément => toutes ces données doivent être stockées en ROM
    => est-ce que vous auriez fait comme ça ?
    => j'ai un doute sur le positionnement des attributs "rom" et "const"...

  2. #2
    Membre actif
    Profil pro
    Inscrit en
    Avril 2009
    Messages
    184
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2009
    Messages : 184
    Points : 288
    Points
    288
    Par défaut
    Attention il me semble qu'il y a une erreur dans ta déclaration du type de pointeur sur fonction, ce serait plutôt :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    typedef void (*TYPE_FUNC_VOIDVOID)(void); // fonction de type : void toto(void)
    du coup, ta struct devient :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    typedef struct _structElement
    {
    	rom char *eltName;
    	rom char *eltDesc;
    	TYPE_FUNC_VOIDVOID ptr_action;
    } structElement;
    puisque TYPE_FUNC_VOIDVOID est déjà un pointeur.
    De même :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    rom const structElement elt1 = { "ma commande1"   , "ma description1", toto};
    rom const structElement elt2 = { "ma commande2"   , "ma description2", tutu};
    Pas de parenthèses, sinon, la valeur de toto() c'est la valeur de retour d'une exécution de la fonction toto et non pas l'adresse de la fonction toto.

    Enfin pour lancer la commande, c'est :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    tabElt[0]->ptr_action();
    Par contre je ne connais pas le qualificatif rom, je pense que ça doit être spécifique à la plateforme non ?

  3. #3
    Membre éprouvé
    Profil pro
    Inscrit en
    Septembre 2009
    Messages
    1 821
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2009
    Messages : 1 821
    Points : 979
    Points
    979
    Par défaut
    merci pour ta réponse

    rom est spécifique a ma plateforme c'est jsute pour dire que la variable est stockée en rom => mais je crois bien que ça fait la même chose si j'utilise const

    par contre es-tu bien sure pour la déclaration du pointeur de fonction ? dans le lien suivant, il n'y a pas de parenthèses :
    http://c.developpez.com/faq/?page=ta...dresse_tableau

  4. #4
    Expert éminent
    Avatar de Melem
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2006
    Messages
    3 656
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Janvier 2006
    Messages : 3 656
    Points : 8 389
    Points
    8 389
    Par défaut
    Citation Envoyé par huit_six Voir le message
    Attention il me semble qu'il y a une erreur dans ta déclaration du type de pointeur sur fonction, ce serait plutôt :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    typedef void (*TYPE_FUNC_VOIDVOID)(void); // fonction de type : void toto(void)
    du coup, ta struct devient :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    typedef struct _structElement
    {
    	rom char *eltName;
    	rom char *eltDesc;
    	TYPE_FUNC_VOIDVOID ptr_action;
    } structElement;
    puisque TYPE_FUNC_VOIDVOID est déjà un pointeur.
    Donc y avait finalement pas erreur dans l'ancienne déclaration de TYPE_FUNC_VOIDVOID (qui était un type "fonction" et que TU as préféré changé directement en "pointeur de fonction").

    Citation Envoyé par boboss123
    Donc pour lancer la commande de l'élément 0, je fais :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    (*tabElt[0]->ptr_action)();
    Le déréférencement est inutile.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    printf("Vive le C !\n");
    (printf)("Vive le C !\n");
    (&printf)("Vive le C !\n");
    (*printf)("Vive le C !\n");
    (**printf)("Vive le C !\n");
    (*************printf)("Vive le C !\n");
    => C'est la même chose. Voir tutos/FAQs.

  5. #5
    Membre éprouvé
    Profil pro
    Inscrit en
    Septembre 2009
    Messages
    1 821
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2009
    Messages : 1 821
    Points : 979
    Points
    979
    Par défaut
    merci beaucoup, ça marche

    mais auriez vous structuré votre projet de la même manière que ce que je fais la (ça me semble pas mal comme solution) ?

  6. #6
    Expert éminent
    Avatar de Melem
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2006
    Messages
    3 656
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Janvier 2006
    Messages : 3 656
    Points : 8 389
    Points
    8 389
    Par défaut
    ça me semble pas mal comme solution
    En effet .

  7. #7
    Membre actif
    Profil pro
    Inscrit en
    Avril 2009
    Messages
    184
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2009
    Messages : 184
    Points : 288
    Points
    288
    Par défaut
    Et bah MINCE alors !

    Je viens d'apprendre quelque chose ! Je ne savais pas qu'il existait de type fonction !

    Je n'en avais jamais entendu parler, je manipulais des pointeurs de fonction, mais pas de types fonction.

    [Edit] Je suis en train de lire ton cours Melem, je savais bien que j'aurai du le faire avant...

  8. #8
    Membre éprouvé
    Profil pro
    Inscrit en
    Septembre 2009
    Messages
    1 821
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2009
    Messages : 1 821
    Points : 979
    Points
    979
    Par défaut
    Citation Envoyé par huit_six Voir le message
    Je n'en avais jamais entendu parler, je manipulais des pointeurs de fonctions, mais pas de types fonction.
    Si tu ne connaissais pas cette astuce, comment créais tu tes pointeurs de fonctions alors ?
    Avant je déclarais mes pointeurs de fonction sur mes structures comme cela :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    typedef struct _structElement {
    	const char *eltName;
    	const char *eltDesc;
    	const void *ptr_action; // pointeur de fonction
    } structElement;
    const structElement elt1; // declaration d'un element
    const structCmd *const tabElt[]; // tableau de struture
     
    void (*p)(); // pas trop compris comment ça marche lol
    => Et depuis que j'ai utilisé la méthode décrite précédemment, j'ai gagné 240 bytes de ROM sur la déclaration/utilisation de ma structure alors que le fonctionnement est le même (ce qui est quand même beaucoup pour mon µC). En plus j'avais des warning sur l'utilisation de la variable p.


    -------------------------------
    En fait c'est trop bien les pointeurs de fonction, on peut meme faire des gestionnaires d'interruptions:

    exemple (pas eu encore le temps de tester) :
    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
     
    // *************************
    // dans le .h
    typedef void TYPE_FONCTION(char); // fonction de type : void toto(char xxx)
    extern void InitModule(TYPE_FONCTION *ptFunc);
    extern void MyProcess(void);
     
     
     
    // *************************
    // dans le .c
     
    static TYPE_FONCTION *_ptFunc;
    static char _state;
     
     
    // envoi l'interruption
    static void _SendInterrupt(void){
    	_ptFunc(_state);
    }
     
    // initialisation du module
    void InitModule(TYPE_FONCTION *ptFunc){
    	_state = 0;
    	_ptFunc = ptFunc;
    }
     
    // Process du module
    void MyProcess(void){
     
    	....
        ....
        ...
    	if (error){
    		_SendInterrupt();
    	}
     
    }
     
     
    // *************************
    // dans l'application
     
    // de
    static void InterruptDetected(state){
     
    	// => traitement de l'interruption
     
    	switch (state){
    		...
    		...
    	}
    }
     
    void main(void){
     
    	InitModule(InterruptDetected); // initialisation
     
    	while (1){
    		MyProcess(); // lancement du processus
    	}
     
    }
    => c'est bien comme ça qu'on gère les interruptions en c ?

  9. #9
    Membre actif
    Profil pro
    Inscrit en
    Avril 2009
    Messages
    184
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2009
    Messages : 184
    Points : 288
    Points
    288
    Par défaut
    Si tu ne connaissais pas cette astuce, comment créais tu tes pointeurs de fonctions alors ?
    Comme dit plus haut :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    typedef void (*TYPE_FUNC_VOIDVOID)(void);
     
    void fonction_debile(void) {
        printf("Ceci est la fonction débile\n");
    }
     
    TYPE_FUNC_VOIDVOID pointeur_de_fonction = fonction_debile;
     
    pointeur_de_fonction();
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    void (*p)(void); /* équivaut à : */
    TYPE_FUNC_VOIDVOID p;
    Le typedef permet juste de rendre (beaucoup) plus lisible.

    Comme je disais, je connaissais le type pointeur de fonction, mais pas le type fonction. Comme il n'est pas utilisable directement, je n'avais pas encore eu l'occasion de le rencontrer.

  10. #10
    Expert éminent sénior

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 603
    Détails du profil
    Informations personnelles :
    Âge : 66
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 603
    Points : 17 913
    Points
    17 913
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par boboss123 Voir le message
    En fait c'est trop bien les pointeurs de fonction, on peut meme faire des gestionnaires d'interruptions:
    ça sert surtout à faire des bibliothèques événementielles, où on enregistre une fonction en fonctions d'événements prévus..

    C'est comme ça que marche toutes les biblothèques graphiques.. Quand tu crées un bouton via un IDE, tu as (en général automatiquement) une routine créée qui s'appelera quelque chose comme OnClick(..).

    Le Widget a, en interne, une action déjà définie sur le "OnClick" (par exemple inverser les ombres pour faire apparaître que le bouton s'enfonce).

    Dans son code, il a aussi un test :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    if ( Registered_Function (WidgetID, ONCLICK) )
       Call_Registered-Function ( WidgetID, ONCLICK )
    ou quelque chose d'équivalent..

    ça permet de fabriquer des biblothèques où le programmeur qui va utiliser la bibliothèque peut rajouter des actions à prendre, sans que la bibliothèque soit au courant (et donc sans recompiler).. En général la biblothèque défini cependant une API standard (pour savoi sur quel obket cela s'applique, quelles données (void) elle doit transmettre telles quelles, et vraisemblablement une structure particulière dépendant du type d'objet concerné (par exemple un PushButton n'aura pas la même structure "publique" qu'une liste ou une scrollbar).



    C'est l'utilisation la plus courante.
    "Un homme sage ne croit que la moitié de ce qu’il lit. Plus sage encore, il sait laquelle".

    Consultant indépendant.
    Architecture systèmes complexes. Programmation grosses applications critiques. Ergonomie.
    C, Fortran, XWindow/Motif, Java

    Je ne réponds pas aux MP techniques

  11. #11
    Membre éprouvé
    Profil pro
    Inscrit en
    Septembre 2009
    Messages
    1 821
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2009
    Messages : 1 821
    Points : 979
    Points
    979
    Par défaut
    oki merci

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

Discussions similaires

  1. Déclaration des structures
    Par DavidleVrai dans le forum Débuter
    Réponses: 5
    Dernier message: 03/05/2013, 15h03
  2. Déclaration de structures et pointeurs de structure
    Par Alpha573 dans le forum Débuter
    Réponses: 1
    Dernier message: 22/11/2011, 18h09
  3. [WD14] Déclaration de structure via compilation dynamique
    Par cladoo dans le forum WinDev
    Réponses: 14
    Dernier message: 15/02/2011, 14h22
  4. Déclaration de structures dépendantes
    Par Dark-Seal dans le forum C
    Réponses: 6
    Dernier message: 02/12/2006, 21h43
  5. déclaration et création de structure.
    Par poporiding dans le forum C++
    Réponses: 4
    Dernier message: 17/01/2006, 10h37

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