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 averti
    Inscrit en
    Février 2009
    Messages
    44
    Détails du profil
    Informations forums :
    Inscription : Février 2009
    Messages : 44
    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 confirmé

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

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 610
    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)

  3. #3
    Membre averti
    Inscrit en
    Février 2009
    Messages
    44
    Détails du profil
    Informations forums :
    Inscription : Février 2009
    Messages : 44
    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 confirmé

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

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 610
    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)

  5. #5
    Membre averti
    Inscrit en
    Février 2009
    Messages
    44
    Détails du profil
    Informations forums :
    Inscription : Février 2009
    Messages : 44
    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
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 68
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    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

  7. #7
    Membre averti
    Inscrit en
    Février 2009
    Messages
    44
    Détails du profil
    Informations forums :
    Inscription : Février 2009
    Messages : 44
    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 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
    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;

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

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    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 ...

  10. #10
    Membre averti
    Inscrit en
    Février 2009
    Messages
    44
    Détails du profil
    Informations forums :
    Inscription : Février 2009
    Messages : 44
    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 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
    ...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)

  12. #12
    Membre averti
    Inscrit en
    Février 2009
    Messages
    44
    Détails du profil
    Informations forums :
    Inscription : Février 2009
    Messages : 44
    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
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 398
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 398
    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 averti
    Inscrit en
    Février 2009
    Messages
    44
    Détails du profil
    Informations forums :
    Inscription : Février 2009
    Messages : 44
    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
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 398
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 398
    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 averti
    Inscrit en
    Février 2009
    Messages
    44
    Détails du profil
    Informations forums :
    Inscription : Février 2009
    Messages : 44
    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 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
    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

  18. #18
    Membre averti
    Inscrit en
    Février 2009
    Messages
    44
    Détails du profil
    Informations forums :
    Inscription : Février 2009
    Messages : 44
    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 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
    jvais virer les globales inutiles

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