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 :

headers include et .c


Sujet :

C

  1. #1
    Membre à l'essai
    Inscrit en
    Février 2009
    Messages
    44
    Détails du profil
    Informations forums :
    Inscription : Février 2009
    Messages : 44
    Points : 20
    Points
    20
    Par défaut headers include et .c
    Hello,

    Je souhaiterais developper (plutot découper) mon programme de la manière suivante :

    programme.c
    h_headers1.h
    h_headers1.c

    Le programme.c étant le code contenant le main() et compilé (gcc programme.c ...) et dans les h_* mettre toutes mes fonctions. Je souhaiterais enfaite que dans le .h il y ait les signatures des fonctions ainsi que le blabla qui va bien (commentaires!) et que dans le .c associé il y ait le code proprement dit de la fonction.

    Deux questions :
    1. Comment faire ? (Je pense à une manière autre que programme.c include h_headers.h qui lui-même include h_headers.c) - Je me disais qu'étant donné qu'ils ont les mêmes nom ça pourrait être implicite à la compilation ?
    2. Y-a-t-il un interet ?


    Merci,

  2. #2
    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 n0mad Voir le message
    Deux questions :
    1. Comment faire ? (Je pense à une manière autre que programme.c include h_headers.h qui lui-même include h_headers.c) - Je me disais qu'étant donné qu'ils ont les mêmes nom ça pourrait être implicite à la compilation ?
    Euh.. Je crois que tu n'as pas compris la notion sous-jacente.

    Le .h contiendra bien la déclaration des fonctions, mais c'est la seule chose qu'on incluera dans programme.C (pour qu'à la compilation il y ait vérification des paramètres et que le compilateur sache que les fonctions sont définies extérieurement.

    Le ...headers.c sera compilé séparément, et lié (phase de link/édition de liens du compilateur) à programme.c, où les références seront résolues..

    Citation Envoyé par n0mad Voir le message
    2. Y-a-t-il un interet ?
    Plusieurs :

    • modularité
    • maintenance
    • fabrication de bibliothèques
    • éventuellement code binaire plus petit (si bibliothèque dynamique)
    "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

  3. #3
    Membre à l'essai
    Inscrit en
    Février 2009
    Messages
    44
    Détails du profil
    Informations forums :
    Inscription : Février 2009
    Messages : 44
    Points : 20
    Points
    20
    Par défaut
    Euh.. Je crois que tu n'as pas compris la notion sous-jacente.
    Ca se discutte, je pencherais plutot pour le fait que je ne sache pas l'implémenter :o)

    Bref, j'ai les trois bout de code suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    // test.c
    #include <stdio.h>
    #include "h_header.h"
    int main(void)
    {
    	printf("bonjour !\n");
    	ma_fonction(5);
    	return 1;
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    // h_header.h
    /* Ma Super Fonction */
    void ma_fonction(int);
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    // h_header.c
    void ma_fonction(int a)
    {
    	printf("a x a = %d\n", a*a);
    }
    Et je compile comme suit :
    ~$ gcc -o test test.c

    et j'obtiens :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    /tmp/ccaWyFH8.o: In function `main':
    test.c:(.text+0x27): undefined reference to `ma_fonction'
    collect2: ld returned 1 exit status
    Donc je dois bien oublier un truc....

  4. #4
    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 n0mad Voir le message
    Donc je dois bien oublier un truc....
    Comme je te l'ai dit au dessus, tu oublies de compiler h_header.c, et de lier test.c (après compilation) à h_header.o (après compil)
    "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

  5. #5
    Membre à l'essai
    Inscrit en
    Février 2009
    Messages
    44
    Détails du profil
    Informations forums :
    Inscription : Février 2009
    Messages : 44
    Points : 20
    Points
    20
    Par défaut
    euh oui j'avais compris mais je demandais comment on fait concrètement ! J'ai du mal m'exprimer.

    J'ai trouvé l'option qui me manquait "-c"
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    ~$ gcc -c h_header.c 
    ~$ gcc -c test.c    
    ~$ gcc h_header.o test.o  -o test
    Merci =)

  6. #6
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par n0mad Voir le message
    Hello,

    Je souhaiterais developper (plutot découper) mon programme de la manière suivante :

    programme.c
    h_headers1.h
    h_headers1.c
    C'est techniquement possible, mais le choix des noms a son importance. En effet, la séparation entre interface (header) et implémentation (source C) est déjà faite par l'extension (.h / .c). Elle ne doit donc pas apparaitre dans le nom (il est est en effet absurde de nommer un .c, 'headers_1.c' ...)

    Il faut au contraire réfléchir à la manière dont on découpe le code. Le but étant de créer une 'unité fonctionnelle' (ou bloc fonctionnel) qui rassemble les fonctions d'une même 'famille'. Cette famille peut être fonctionnelle (entrées sécurisées, affichage spécialisé etc.) ou formée autour d'un objet (structure de donnée et ensemble de fonctions permettant de la manipuler).

    Tout cela n'es en aucun cas du au hasard, mais découle du processus de gestion du projet, et notamment des phases 1 (définition) et surtout 2 (conception) qui sont justement là pour organiser le développement en unités de travail homogènes (les blocs fonctionnels) le plus souvent matérialisés par un couple .h / .c. Par exemple, le bloc fonctionnel xxx est composé de xxx.h et xxx.c. (au minimum).

    Le programme.c étant le code contenant le main() et compilé (gcc programme.c ...) et dans les h_* mettre toutes mes fonctions. Je souhaiterais enfaite que dans le .h il y ait les signatures des fonctions ainsi que le blabla qui va bien (commentaires!) et que dans le .c associé il y ait le code proprement dit de la fonction.

    Deux questions :
    1. Comment faire ? (Je pense à une manière autre que programme.c include h_headers.h qui lui-même include h_headers.c) - Je me disais qu'étant donné qu'ils ont les mêmes nom ça pourrait être implicite à la compilation ?
    2. Y-a-t-il un interet ?
    J'explique ici la démarche sous Code::Blocks :

    http://video.google.fr/videoplay?doc...17817010204120
    Pas de Wi-Fi à la maison : CPL

  7. #7
    Membre à l'essai
    Inscrit en
    Février 2009
    Messages
    44
    Détails du profil
    Informations forums :
    Inscription : Février 2009
    Messages : 44
    Points : 20
    Points
    20
    Par défaut
    Hello,

    Merci pour vos réponses... mais ya encore une coui**e dans le potage..

    Bref voila 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
     
    // session.h
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
     
    #ifndef _H_SESSION_H
    #define _H_SESSION_H 
     
    char *LOG      = NULL;
    char *SESSION  = NULL;
     
    void start_session(char *, int);
    #endif
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    // session.c
    #include "session.h"
     
    void start_session(char *name, int flag)
    {
            printf("bonjour\n");
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    // main - test.c
    #include <stdio.h>
    #include "session.h"
     
    int main(void)
    {
    	start_session("toto",1);
    	return 1;
    }

    La compilation :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    ~$ gcc -Wall -c session.c
    ~$ gcc -Wall -c test.c
    ~$ gcc -Wall session.o test.o -o test
    session.o et test.o sont produit correctement, mais à l'assemblage finale ça coince avec :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    test.o:(.bss+0x0): multiple definition of `LOG'
    session.o:(.bss+0x0): first defined here
    test.o:(.bss+0x4): multiple definition of `SESSION'
    session.o:(.bss+0x4): first defined here
    collect2: ld returned 1 exit status
    Help (je dirais que ça viens du session.h qui est ajouté dans le test.c et dans le session.c ...mais du fais de mon #ifndef / #define je ne comprends pas !)

    Merci de votre aide (moi ye né pas être développeur!)

    :-)

  8. #8
    Expert éminent sénior
    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
    Points : 13 926
    Points
    13 926
    Par défaut
    La compilation des deux .c est faite séparément. Le .h est donc inclus dans les deux .c au moment de leur compilation.
    Alors, il trouve deux globales définies deux fois: LOG et SESSION.

    Ton erreur est de définir des globales dans un .h.
    Un .h ne doit contenir que des définitions de types ou des prototypes ou des #define ... Jamais de définitions de variables.
    Définis tes globales dans un .c (si vraiment tu en as besoin) et dans le .h déclares les en extern :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    //.h
    extern char *LOG ;
    //.c
    char * LOG = NULL;
    Publication : Concepts en C

    Mon avatar : Glenn Gould

    --------------------------------------------------------------------------
    Une réponse vous a été utile ? Remerciez son auteur en cliquant le pouce vert !

  9. #9
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par diogene Voir le message
    Ton erreur est de définir des globales dans un .h.
    Mais la véritable erreur est d'utiliser des globales totalement injustifiées ici ...
    Pas de Wi-Fi à la maison : CPL

  10. #10
    Membre à l'essai
    Inscrit en
    Février 2009
    Messages
    44
    Détails du profil
    Informations forums :
    Inscription : Février 2009
    Messages : 44
    Points : 20
    Points
    20
    Par défaut
    Ouki ... donc je créer "globals.c" comme ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    // globals.c
    char *LOG        = NULL;
    char *SESSION = NULL;
    et puis donc dans mon session.h je fais la même chose en ajoutant le mot extern devant les définitions.

    ...mais euh...le globals.c je l'inclu quand et ou ? :-)

    Citation Envoyé par Emmanuel Delahaye Voir le message
    Mais la véritable erreur est d'utiliser des globales totalement injustifiées ici ...
    Mwais euh ce genre de réflexion c'est pas franchement utile car quand je pose une question je réduis le code pour ne montrer que l'essentiel....donc bon....

  11. #11
    Expert éminent sénior
    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
    Points : 13 926
    Points
    13 926
    Par défaut
    ...mais euh...le globals.c je l'inclu quand et ou ? :-)
    Nulle part, un .c n'a pas vocation à être inclus. Tu n'es pas forcé de créer un .c supplémentaire pour définir tes deux variables globales (si vraiment tu en as besoin)
    Publication : Concepts en C

    Mon avatar : Glenn Gould

    --------------------------------------------------------------------------
    Une réponse vous a été utile ? Remerciez son auteur en cliquant le pouce vert !

  12. #12
    Membre à l'essai
    Inscrit en
    Février 2009
    Messages
    44
    Détails du profil
    Informations forums :
    Inscription : Février 2009
    Messages : 44
    Points : 20
    Points
    20
    Par défaut
    Ah oui je l'ai rajouté dans les objets tout simplement et ça roule ! merci diogene !
    gcc -Wall -O3 -fomit-frame-pointer session.o globals.o test.o -o test



    Bon sinon votre vraiment commence vraiment à m'ennerver ! Plus sérieusement, j'en ai besoin de ces variables globales car plusieurs fonctions (dans différents .c) y accèdent et j'ai besoin que chaque fonction ait l'état précédent.... donc sinon faudrait que je me fasse des listes d'arguments dans mes fonctions et ça me fait tout simplement chier ! ....ah moins que vous ayez des arguments en ce sens ?

    Pourquoi devrais-je éviter les variables gloables ?

  13. #13
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Variable globales --> Manque de thread-safety, manque de réentrance, risque de collision de noms.

    La solution: Employer une structure, et passer à chacune de tes fonctions un pointeur vers cette structure.
    C'est ce qui est fait pour les fonctions de fichier, par exemple...
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  14. #14
    Membre à l'essai
    Inscrit en
    Février 2009
    Messages
    44
    Détails du profil
    Informations forums :
    Inscription : Février 2009
    Messages : 44
    Points : 20
    Points
    20
    Par défaut
    Uhm justement mon programme est a base de threads !

    Enfaite j'ai une structure (variable globale) qui est initialisée, et les threads font des calculs sur cette structure : ils se partagent une ressource. Et je ne veux pas que chacun des threads ait sa propre ressource (car je "divise" le travail de la sorte).

  15. #15
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Dans ce cas, une synchronisation est nécessaire.
    Les objets de synchronisation, eux, sont généralement exempts de tout grief que j'ai contre les variables globales.

    Mais tu peux aussi partager lesdites données (et objets de sync) par pointeur, plutôt que par variables globales. Ça reste plus propre.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  16. #16
    Membre à l'essai
    Inscrit en
    Février 2009
    Messages
    44
    Détails du profil
    Informations forums :
    Inscription : Février 2009
    Messages : 44
    Points : 20
    Points
    20
    Par défaut
    pour la synchro j'utilise les mutex.

    Sinon je ne suis pas sur de voir ce que veux dire avec le partage par pointeurs, tu aurais un exemple stp?

  17. #17
    Expert éminent sénior
    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
    Points : 13 926
    Points
    13 926
    Par défaut
    Bon sinon votre vraiment commence vraiment à m'ennerver !
    J'en suis navré. Mais, tu fais ce que tu veux. C'est ton programme. On se contente de te donner des conseils, tu en fais ce que tu veux.

    donc sinon faudrait que je me fasse des listes d'arguments dans mes fonctions et ça me fait tout simplement chier ! ....ah moins que vous ayez des arguments en ce sens ?
    Je sais que c'est la raison pour laquelle beaucoup introduisent des globales. Mais cette raison est la mauvaise raison (sans vouloir t'énerver le moins du monde ).

    Les variables globales font que les fonctions qui les utilisent cessent d'être "autonomes". Leur comportement ne peut être déduit de leur code seul ; elles dépendent d'éléments qui leur sont extérieurs et qui peuvent être altérés par d'autres fonctions sans que cela apparaisse. Elles sont donc difficiles à écrire (oui !), à comprendre et à tester dans toutes les situations possibles y compris les moins probables.
    Si un problème se pose, la question sera de savoir qui, dans tout le programme, a pu mettre une valeur inattendue dans ces globales.

    Cela simplifie peut être le travail de frappe du code, mais, très souvent, on le paye au prix fort plus tard.

    Mon opinion, pour résumer et si je n'ai pas été assez clair, est que ce sont des pestes
    Publication : Concepts en C

    Mon avatar : Glenn Gould

    --------------------------------------------------------------------------
    Une réponse vous a été utile ? Remerciez son auteur en cliquant le pouce vert !

  18. #18
    Membre à l'essai
    Inscrit en
    Février 2009
    Messages
    44
    Détails du profil
    Informations forums :
    Inscription : Février 2009
    Messages : 44
    Points : 20
    Points
    20
    Par défaut
    lol diogène ! Ne t'inquiete pas je ne m'ennerve pas je disais cela en rigolant (a cause du jeu de mot...) bref, ton explication a du sens et je n'y avait pas pensé... jvais virer les globales inutiles =)

    merci

  19. #19
    Expert éminent sénior
    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
    Points : 13 926
    Points
    13 926
    Par défaut
    jvais virer les globales inutiles
    Publication : Concepts en C

    Mon avatar : Glenn Gould

    --------------------------------------------------------------------------
    Une réponse vous a été utile ? Remerciez son auteur en cliquant le pouce vert !

Discussions similaires

  1. Header & Include
    Par Ronan_ dans le forum C++
    Réponses: 6
    Dernier message: 24/03/2014, 11h41
  2. [Cookies] headers include
    Par Oprichnik dans le forum Langage
    Réponses: 6
    Dernier message: 22/09/2007, 15h42
  3. Réponses: 2
    Dernier message: 07/03/2006, 01h53
  4. [VC++] Problème include de header
    Par Yellowmat dans le forum MFC
    Réponses: 10
    Dernier message: 08/12/2005, 13h50
  5. [compil] #include <header> ou #include <head
    Par guejo dans le forum MFC
    Réponses: 5
    Dernier message: 02/06/2004, 15h31

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