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 :

Problème de typedef et headers multiples


Sujet :

C

  1. #1
    Futur Membre du Club Avatar de Narmondil
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2019
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2019
    Messages : 3
    Points : 8
    Points
    8
    Par défaut Problème de typedef et headers multiples
    Bonjour,

    Dans le cadre d'un cours de licence, nous travaillons sur un projet de compression de Huffman en C.
    La compilation demandée est en ANSI avec option pedantic (et evidemment le Wall et Werror qui vont avec).
    L'arborescence du projet nous est imposée et se compose de divers codes source et headers correspondants.
    Dans plusieurs de ces headers il y a des typedefs de structures auto-référentes et autres.

    J'ai bien vérifié que chaque header utilisant une variable ou un type défini dans un autre header importe celui-ci, idem pour le code source. Cependant, à la compilation, j'obtiens toujours les warnings suivants (je n'en mets qu'un pour illustrer mais j'en obtiens plusieurs concernant différents headers) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    coding.h:10:1: warning: parameter names (without types) in function declaration
     arbre_t construirecodage(freq_t);
    Je suppose que le souci provient du fait que le lien entre les header où est réalisé le typedef et celui où le type est utilisé ne se fait pas correctement, ce qui fait qu'ici par exemple arbre_t est analysé comme un nom de variable et non comme un type. Sauf que j'ignore comment solutionner ça. Ou peut-être que le problème vient d'ailleurs mais je sèche.


    Code du header coding.h en exemple
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    #ifndef CODING_H
    #define CODING_H
     
    #include "freq.h" /* freq_t */
    #include "arbre.h" /* arbre_t */
     
    typedef unsigned int code_t[257];
     
    arbre_t construirecodage(freq_t);
    void encode_rec(arbre_t, code_t, int);
     
    #endif /* CODING_H */

    Code du header contenant le typedef d'arbre_t en exemple
    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
     
    #ifndef ARBRE_H
    #define ARBRE_H
     
    #define HAUTEUR_MAX 31
     
    typedef struct noeud_m* arbre_t;
     
    struct noeud_m {
      float freq;
      int lettre;
      unsigned int code;
      arbre_t left;
      arbre_t right;
    };
     
    (...)
    #endif /* ARBRE_H */
    Toute piste de reflexion et/ou solution sera la bienvenue.

  2. #2
    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
    L'erreur étant sur freq_t, il aurait mieux fallu montrer le header freq.h que arbre.h
    Mais si freq_t est déclaré comme l'est arbre_t, alors freq_t n'existe pas plus que arbre_t.
    En C, quand on déclare struct Toto {};, on ne définit pas un type Toto mais un type struct Toto.
    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.

  3. #3
    Futur Membre du Club Avatar de Narmondil
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2019
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2019
    Messages : 3
    Points : 8
    Points
    8
    Par défaut
    Merci pour ta réponse.

    Citation Envoyé par Bousk Voir le message
    L'erreur étant sur freq_t, il aurait mieux fallu montrer le header freq.h que arbre.h
    Comme le terminal m'indique via la surbrillance arbre_t, je pensais que c'était cette structure qui posait problème, mais comme je l'ai dit j'ai d'autres messages d'erreurs similaires. Voici donc le code de freq.h

    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
     
    #ifndef FREQ_H
    #define FREQ_H
     
    #include <stdio.h> /* FILE* */
    #include "coding.h"
     
    typedef float freq_t[257];
     
    void reset_tab(code_t);
    unsigned int build_array_nb_occurrences(FILE*);
    void build_array_freq(unsigned int);
    void frequence(freq_t , FILE*);
     
    #endif /* FREQ_H */
    Citation Envoyé par Bousk Voir le message
    Mais si freq_t est déclaré comme l'est arbre_t, alors freq_t n'existe pas plus que arbre_t.
    En C, quand on déclare struct Toto {};, on ne définit pas un type Toto mais un type struct Toto.
    Jusque là nous avons toujours manipulé les structures autoréférentes somme ça et ça n'a jamais planté à la compilation.
    Avec un typedef struct maStructure monType; suivi de la déclaration de la structure struct maStructture { }; justement pour ne pas avoir à réécrire struct xxx à chaque fois mais juste xxx. La déclaration d'un pointeur sur une structure suivait toujours le schéma typedef struct noeud_m* arbre_t; Du coup je ne comprends pas pourquoi ça ne fonctonnerait plus maintenant . Autre point à noter qui fait que ce n'est pas ce morceau de code dont j'ai douté en premier, ce header fait partie du matériel qu'on a forké depuis le git du cours, donc j'ai supposé qu'il n'y avait pas d'erreurs de ce genre.

    Un conseil sur comment solutionner le problème du coup?

  4. #4
    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
    My bad, j'ai mélangé arbre_t et noeud_m...
    Montre-nous toutes les erreurs. Souvent la première entraîne les autres qui n'en sont pas.
    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.

  5. #5
    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 Narmondil Voir le message
    La déclaration d'un pointeur sur une structure suivait toujours le schéma typedef struct noeud_m* arbre_t;
    C'est généralement maladroit de cacher un pointeur derrière un type pour plusieurs raisons
    • le pointeur est un élément important du C. Le codeur qui relit/modifie/fait évoluer ton code a besoin de les connaitre pour pas faire d'erreur. Le cacher derrière un type masque cette information
    • même si créer un type masque l'étoile, celle-ci reviendra dès qu'on utilisera "adresse de". Si par exemple var est de type arbre_t (ou struct noeud_m*), alors &var sera du type arbre_t* (ou struct noeud_m**). Bref l'étoile ne sera pas restée cachée longtemps (et tu auras alors obfusqué ton code pour pas grand chose)
    • le codeur habitué du C sait manipuler les pointeurs de façon assez naturelle et n'a donc aucun besoin de se les cacher pudiquement

    Autrement dit, masquer l'étoile derrière un type est plus néfaste qu'autre chose.

    Autre truc (qui m'avait été quand je débutais ici dit par Emmanuel Delahaye, un pilier de ce forum qui a décidé de quitter la prog il y a une dizaine d'années): le suffixe "_t" est généralement réservé aux types officiels de la libC (size_t, ptr_t, etc). Les types créés par les utilisateurs doivent être préfixés "t_" (t_arbre, t_freq, etc) et non suffixés pour ne pas créer de collision. Toutefois c'est bien déjà de l'avoir mis (si tu savais comme ça me hérisse quand je vois des débutants arriver avec leurs typedef struct {...} noeud et utilisés ensuite dans leur stupide noeud Noeud)...

    Citation Envoyé par Narmondil Voir le message
    Un conseil sur comment solutionner le problème du coup?
    Peut-être, dans "coding.h", définir "code_t" avant d'inclure "freq.h" qui l'utilise, pour le coup, sans le connaitre. Parce que, bien que "freq.h" inclut "coding.h", comme le "CODING_H" est alors déjà défini, celui-ci est alors intégralement ignoré et "freq.h" continue alors sur void reset_tab(code_t) sans connaitre "code_t".
    Ce n'est pas tout à fait la ligne que tu décris mais c'est le souci que moi j'ai eu quand j'ai repris tous tes ".h" et voulu les compiler. Donc peut-être que...
    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]

  6. #6
    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
    Je viens de voir
    > coding include freq
    > freq include coding
    Ça va forcément péter un moment, et tu es face à ce moment.
    Je vois pas en quoi freq aurait besoin de connaître coding. Si ce n'est parce que reset_tab est mal placé.
    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.

  7. #7
    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 Bousk Voir le message
    Je viens de voir
    > coding include freq
    > freq include coding
    Ça va forcément péter un moment,
    Non, il a bien mis les barrières anti include récursif donc ça ne pétera pas. Mais l'un des deux #include ne se fait pas.

    Citation Envoyé par Bousk Voir le message
    Je vois pas en quoi freq aurait besoin de connaître coding. Si ce n'est parce que reset_tab est mal placé.
    Oui. On le placerait dans "coding.h" ce serait peut-être mieux. Mais à mon avis le best-of serait d'écrire un "code.h" qui définirait code_t...
    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]

  8. #8
    Futur Membre du Club Avatar de Narmondil
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2019
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2019
    Messages : 3
    Points : 8
    Points
    8
    Par défaut
    Bonjour,

    Merci à vous pour les réponses. C'était bien ça le problème, l'odre des include. Comme le tout était circulaire ça ne fonctionnait pas puisque certains #include ne se faisaient pas... il m'a donc fallu réorganiser les headers, mettre certains typedefs avant des include... oui c'est sale, mais ça a réglé le souci de compilation.

    Citation Envoyé par Sve@r Voir le message
    C'est généralement maladroit de cacher un pointeur derrière un type
    Merci d'écrire ça, j'ai toujours été horrifié de voir ce genre de manipulation car je trouve qu'on oublie vite à quel niveau on en est foo* bar; peut ainsi déclarer un pointeur de pointeur et non un pointeur si foo est déjà un pointeur de quelque chose. Je trouve que c'est de l'obfuscation de code gratuite. Mais c'est ce qu'on nous demande dans l'Université où je suis. Donc comme c'est un projet à rendre, je me plie aux règles... mais je n'en pense pas moins.

    Citation Envoyé par Sve@r Voir le message
    Autre truc (qui m'avait été quand je débutais ici dit par Emmanuel Delahaye, un pilier de ce forum qui a décidé de quitter la prog il y a une dizaine d'années): le suffixe "_t" est généralement réservé aux types officiels de la libC (size_t, ptr_t, etc). Les types créés par les utilisateurs doivent être préfixés "t_" (t_arbre, t_freq, etc) et non suffixés pour ne pas créer de collision.
    Encore une fois, je ne faisais que reproduire ce qu'on nous a appris en cours mais je prends note pour le préfixage, ça semble effectivement important de ne pas prendre de risques inutilles en jouant avec la nomenclature.

    Merci pour votre aide et vos conseils.

  9. #9
    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
    Citation Envoyé par Sve@r Voir le message
    Non, il a bien mis les barrières anti include récursif donc ça ne pétera pas. Mais l'un des deux #include ne se fait pas.
    Ça va pas péter dans le sens erreur et déclaration multiple.
    Ça pète dans le sens espérer utiliser des trucs de l'autre fichier alors qu'il ne sera pas inclus puisqu'il est déjà en train d'être inclus.
    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.

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

Discussions similaires

  1. Problèmes d'affiche du header de mon JTable avec un Model
    Par Baptiste Wicht dans le forum Composants
    Réponses: 16
    Dernier message: 08/02/2006, 18h37
  2. [Mail] Problème d'affichage d'HEADERS avec mail();
    Par JeanMi66 dans le forum Langage
    Réponses: 3
    Dernier message: 17/01/2006, 06h46
  3. Problème Total dans un header
    Par snoop57 dans le forum IHM
    Réponses: 8
    Dernier message: 06/12/2005, 15h15
  4. Problème entre 2 listbox à selection multiple
    Par SoaB dans le forum Général JavaScript
    Réponses: 24
    Dernier message: 24/10/2005, 16h05
  5. [Dates] Problème avec la fonction header
    Par d.w.d dans le forum Langage
    Réponses: 2
    Dernier message: 06/09/2005, 16h33

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