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 compilation séparée


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé
    Avatar de exe2bin
    Profil pro
    Passionné de programmation
    Inscrit en
    Mars 2009
    Messages
    537
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Passionné de programmation

    Informations forums :
    Inscription : Mars 2009
    Messages : 537
    Billets dans le blog
    3
    Par défaut Problème compilation séparée
    Bonjour à tous ;
    Je n'y arriverait jamais avec la compilation séparée ....
    J'ai un gros fichier (+500 lignes) et ça commence à être pesant de s'y retrouver alors je me suis dit : " y a qu'a fragmenter en plusieurs fichier !!"
    Pas mal me direz-vous; surtout que je l'ai déjà fait mais voilà : en ce qui concerne les fonctions c'est relativement aisé :
    un fichier.h avec les signatures puis le fichier.c qui va avec ; on inclut le fichier.h dans tout fichier.c qui veut utiliser les fonctions et basta !
    Mais ce que je ne suis jamais parvenu à faire c'est gérer les variables globales ?!
    Comment faire pour signifier au fonctions qui s'en servent que celles-ci sont définies ailleurs (le mot clé extern ne suffit apparement pas) ,où et comment
    procéder ???
    C'est un aspect du C qui me gonfle grave !!!

  2. #2
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 815
    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 815
    Billets dans le blog
    1
    Par défaut
    Bonjour

    T'inquiète pas, on va t'expliquer ça bien

    Quand tu compiles un source, tu dois déclarer les variables que le source va utiliser. "Déclarer" signifie "indiquer leur existence". Quand ensuite tu veux créer l'exécutable, tu dois "définir" les variables, c'est à dire "les créer en mémoire" (si tu regardes mes posts en détails, tu verras que je fais très attention à l'emploi de ces deux verbes chaque fois que je parle de variables).
    Généralement, la définition englobe aussi la déclaration. Surtout quand tu n'as qu'un seul source et que tu compiles et crées l'exécutable d'un coup. Mais dans le cas de plusieurs sources, alors il faut déclarer les variables dans chaque source qui va l'utiliser mais la définir une seule et unique fois.

    La déclaration se fait via le mot clef extern qui signifie grosso-modo pour le compilo "considère qu'elle existe, t'inquiète pas elle sera définie plus tard". Donc fatalement à un endroit il faut quand-même la définir donc la déclarer sans mettre "extern". Mais il ne faut le faire que dans un seul source sinon il y aura conflit lors de l'édition de liens.

    Bon moi je n'utilise pas de globales. Mais si je devais en mettre, alors je la définirais dans le source qui contient le main et la déclarerais en extern dans les autres.

    Exemple
    fichier "main.c"
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    int glob;
    int main() {
    	glob=123;
    	affiche();
    }

    Fichier "affiche.c"
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    extern int glob;
    void affiche() {
    	printf("glob=%d\n", glob);
    }

    A noter: les programmeurs n'aiment pas les globales principalement parce que si la variable est accidentellement modifiée, il devient difficile de déterminer qui l'a modifiée. Une astuce permettant "d'aider" à la détection est de redéclarer dans la fonction les variables globales utilisées par la fonction.

    Exemple
    fichier "main.c"
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    int glob;
    int main() {
    	extern int glob;		// Comme ça, les autres lecteurs savent que cette fonction utilise la variable globale "glob"
    	glob=123;
    	affiche();
    }

    Fichier "affiche.c"
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    extern int glob;
    void affiche() {
    	extern int glob;		// Pareil
    	printf("glob=%d\n", glob);
    }
     
    void toto() {
    	// Cette fonction n'utilise pas "glob", je ne la déclare donc pas ici
    	... autre_chose_mais_sans_utiliser_glob...
    }
    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]

  3. #3
    Membre éclairé
    Avatar de exe2bin
    Profil pro
    Passionné de programmation
    Inscrit en
    Mars 2009
    Messages
    537
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Passionné de programmation

    Informations forums :
    Inscription : Mars 2009
    Messages : 537
    Billets dans le blog
    3
    Par défaut
    Merci de ta patience mais j'ai 2 questions (au moins) :

    1) est ce cela marche aussi pour les déclarations de structures et à fortiori pour les tableaux (pour lesquels on doit déclarer la taille) ?

    2) peut on grouper toutes les déclarations (extern donc) dans un fichier.h puis inclure ce fichier dans tout.c qui l'utilise ?

  4. #4
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 815
    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 815
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par exe2bin Voir le message
    1) est ce cela marche aussi pour les déclarations de structures et à fortiori pour les tableaux (pour lesquels on doit déclarer la taille) ?
    On n'applique le mot clef extern que pour les variables. Donc pour déclarer une structure ou un type (donc sans y mettre immédiatement de variable style typedef struct s_monType {...} t_monType) alors non.
    Mais pour déclarer ensuite des variables de type "struct s_monType" ou "tableau" ou "t_monType" oui ça fonctionne pareil.

    Citation Envoyé par exe2bin Voir le message
    2) peut on grouper toutes les déclarations (extern donc) dans un fichier.h puis inclure ce fichier dans tout.c qui l'utilise ?
    Oui. On peut même faire un truc universel grace à l'inclusion conditionnelle
    Exemple
    Fichier "glob.h"
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    #ifndef __MAIN__
    #define EXTERN extern
    #else // __MAIN__
    #define EXTERN
    #endif // __MAIN__
     
    EXTERN int glob;

    Fichier "main.c"
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    #define __MAIN__
    #include "glob.h"
     
    int main() {
    	glob=123;
    	affiche();
    }

    Fichier "affiche.c"
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    #include "glob.h"
     
    void affiche() {
    	printf("glob=%d\n", glob);
    }

    Lors de l'inclusion de "glob.h" dans le main.c, comme la macro __MAIN__ est définie, alors le mot "EXTERN" étant défini à rien n'aura aucun effet et le compilateur verra int glob. En revanche, dans les autres, comme elle n'est pas définie, le compilo verra extern int glob.
    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]

  5. #5
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2009
    Messages
    4 493
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 493
    Billets dans le blog
    1
    Par défaut
    Au-delà des considérations techniques de réussir à faire compiler ton programme, je te mets en garde (comme Svear l'a deja fait) sur le simple fait d'utiliser des variables globales. C'est pratique dans de petits programmes mais des que tu vas arriver sur des projets un peu plus gros ou si tu souhaites réutiliser des bouts de ton code dans un nouveau projet, tu verras vite que les variables globales sont une plaie... J'avais écrit un article à ce sujet https://gradot.wordpress.com/2014/07...globales-en-c/ mais Google regorge d'autres articles qui abondent dans le même sens. Sans tomber dans l'extrémisme, penses-y ! Et souvent ce n'est pas compliqué

  6. #6
    Membre éclairé
    Avatar de exe2bin
    Profil pro
    Passionné de programmation
    Inscrit en
    Mars 2009
    Messages
    537
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Passionné de programmation

    Informations forums :
    Inscription : Mars 2009
    Messages : 537
    Billets dans le blog
    3
    Par défaut
    C'est vraiment très compliqué pour moi ....

    alors que tout semblait réglé en ce qui concerne les déclarations de fonctions j'obtiens maintenant des messages style :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    duplicate symbol _g_jeu in:
        /var/folders/bv/g3fz_2_54zz50nwkvr1y1gz00000gq/T/ginRummyV5-d75564.o
        /var/folders/bv/g3fz_2_54zz50nwkvr1y1gz00000gq/T/void(void)-d5c2f6.o
    concernant plusieurs de mes variables globales ?!

  7. #7
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 815
    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 815
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par exe2bin Voir le message
    alors que tout semblait réglé en ce qui concerne les déclarations de fonctions j'obtiens maintenant des messages style :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    duplicate symbol _g_jeu in:
        /var/folders/bv/g3fz_2_54zz50nwkvr1y1gz00000gq/T/ginRummyV5-d75564.o
        /var/folders/bv/g3fz_2_54zz50nwkvr1y1gz00000gq/T/void(void)-d5c2f6.o
    concernant plusieurs de mes variables globales ?!
    Sans le source complet de ton ginRummy ça semble compliqué de bien t'aider mais à priori il semblerait que ta variable "g_jeu" ait été définie (attention au sens de ce verbe) deux fois. C'est à dire que par deux fois (on va présumer qu'il s'agit de deux sources différents) tu l'as présentée au compilateur sans mettre le mot "extern" devant.
    Donc la compilation des .c en .o s'est faite sans problème mais à l'édition de liens, le linker avait deux références à deux variables distinctes portant le même nom => duplicate symbol.
    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]

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

Discussions similaires

  1. Problème pour la compilation séparée
    Par mylha dans le forum Débuter
    Réponses: 2
    Dernier message: 29/03/2011, 16h44
  2. Problème de compilation séparée
    Par vincent.mbg dans le forum C
    Réponses: 5
    Dernier message: 14/06/2010, 10h40
  3. Problème simple de compilation séparée
    Par chrisdayton dans le forum Débuter
    Réponses: 7
    Dernier message: 03/12/2009, 07h50
  4. Problème de compilation séparée
    Par orfix dans le forum C
    Réponses: 9
    Dernier message: 25/06/2007, 11h07
  5. Problème de compilation séparée
    Par Kryptonaute dans le forum C
    Réponses: 13
    Dernier message: 16/05/2007, 11h08

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