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 :

compilation de prog multi-modules (bis)


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Profil pro
    amateur
    Inscrit en
    Avril 2012
    Messages
    145
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : amateur
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Avril 2012
    Messages : 145
    Par défaut compilation de prog multi-modules (bis)
    Bonjour,

    Je reviens différemment sur ce thème, déjà évoqué dans un précédent fil: http:[i]http://www.developpez.net/forums/d12...multi-modules/. Désolé pour ce message très long, mais j'essaie de faire le tour de la question en procédant logiquement, dans la mesure de mes moyens, et en abordant les divers aspects souvent laissés implicites du sujet, ainsi que les liens (sic!) entre ces aspects.

    J'essaie de comprendre:
    1. Les rôles respectifs des fichiers sources .c et .h .
    2. Les rôles respectifs de l'inclusion (#include) et du "liage" explicite.
    Je veux par ce dernier point l'indication explicite d'un nom de fichier (compilé) sur la ligne de commande d'édition de lien. Ce que je voudrais, au-delà de "comment faire?", arriver à comprendre assez clairement comment ça marche.

    Pour ça j'utilise le programme exemple suivant:
    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
    // prog.c
    #include "salut.c"   [i] cette ligne-là change *******
    int main () {
       salut () ;
       return 1 ;
    }
     
    // salut.c
    #include <stdio.h>
    void salut () {
       puts ("Salut au monde !") ;
    }
     
    // salut.h
    void salut () ;
    Exploration:
    * Sans la ligne Astérix (;-), pas de compil.
    * En incluant l'un ou l'autre salut.*, la compil roule.
    * En incluant salut.h seul, le liage plante.
    * En incluant salut.c seul, le liage et l'exécution roulent.
    * Inclure .c et .h à la fois ne change rien: ça roule.
    Alors l'édition de lien, là je la fais sans indication d'autre fichier que prog.o:
    gcc -Wall -o prog prog.c

    Déjà, je viens de réaliser réellement que l'incluson "physique" (sic!) des fichiers fait que le compilateur sait déjà presque tout sur la totalité de l'appli (sauf s'il y a incohérence entre une déclaration dans un fichier et la définiton correspondante ailleurs, ou son absence). Mais alors, que rajoute la distinction entre .c et .h? et celle entre compilation et édition de liens? Là, je pige plus trop.

    J'ai dans l'idée que les deux marchent ensemble, et qu'ils ne servent qu'à faire de la compilation séparée. Les .h auraient pour but d'empêcher le compilateur de râler lorsqu'on compile séparément un module qui utilise des fonctionnalités externes (tiens, à propos, extern, encore un sujet à comprendre), en lui disant en gros "fais moi confiance, ce truc-là existe et il est comme j'te dis".
    Très bien mais pour moi, sur une machine moderne, tant que le projet ne dépasse pas une certaine échelle, ça ne sert pas à grand chose. (Surtout que le compilo ne va pas recompiler les fichiers inchangés.) Et encore moins en phase de développement où l'optimisation (ce qui bouffe l'essentiel du temps de compil) est plus que secondaire.
    Le truc, donc, ce serait de mettre les déclarations uniquement dans le .h, et de compiler en incluant seulement cela. Ce qui allège et accélère le processus. Ensuite, au liage, au lieu d'inclure les .c (ce qui imposerait une recompilation), on les indique à l'éditeur de lien explicitement. Est-ce que mon raisonnement est correct?
    [HS: y a pas des mots français pour link, linker, linking? Pourquoi lier, lieur, liage (ou liaison ;-) ne sont-ils pas utilisés? On pourrait aussi dire re-lieur, re-lier rel-liage.]

    Pour en revenir à mes problèmes, il me semble qu'il n'y a pas de différence fonctionnelle entre l'inclusion à la compilation et le "reliage" a posteriori. Je veux dire par là que mon prog fonctionnera strictement pareil si j'inclue le .c (avec ou sans .h) ou si j'inclue le .h seul et "relie" ensuite le .c. Est-ce que j'ai raison?
    Je vérifie que ça marche, au moins (compil avec .h seul):

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    spir@ospir:~/prog/C/comp$ gcc -Wall -o prog salut.o prog.o
    spir@ospir:~/prog/C/comp$ ./prog
    Salut au monde !
    Alors est-ce que cette ligne de raisonnement est valable quelle que soit l'architecture du projet: je peux toujours soit inclure les .c (les fichiers qui contiennent les définitions explicites) (avec les .h si les déclarations sont exportées) à la compilation, soit inclure les .h (les fichiers qui contiennent les définitions explicites) uniquement et relier les .c à l'édition de lien seulement. Correct?

    J'ai encore un petit problème. Je modifie mon programme ainsi, ce qui exporte la définition de 'salutation':
    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
    // prog.c
    #include "salut.h"
    int main () {
       salut () ;
       return 1 ;
    }
     
    // salut.c
    #include <stdio.h>
    #include "salut.h"
    void salut () {
       puts (salutation) ;
    }
     
    // salut.h
    #ifndef H_SALUT
    #define H_SALUT
    const char * salutation = "Salut au monde !";
    void salut () ;
    #endif
    Là, malgré le #ifndef dans salut.h, j'ai une erreur à l'édition de lien (qui comme plus haut indique salut.o explicitement):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    spir@ospir:~/prog/C/comp$ gcc -Wall -o prog salut.o prog.o
    prog.o:(.data+0x0): multiple definition of `salutation'
    salut.o:(.data+0x0): first defined here
    C'est tout-à-fait logique si je comprends bien: du fait de la compilation séparée, prog.c et salut.c incluent tous deux salut.h, malgré la précaution du #ifndef. Correct? Mais je suis bien obligé de l'inclure dans chacun, pour compiler, non? Je peux aussi dans prog.c inclure salut.c au lieu de salut .h, mais c'est pas ça le but du jeu, car là je compile avec prog.c la totalité du programme, ce n'est plus de la compilation séparée en fait. Alors quelle est la méthode que je n'ai pas trouvée tout seul?

    Le but à terme pour moi est de définir la manière la plus pratique d'utiliser les outils C avec mon style de programmation "exploratoire". Ce style, en gros, du point de vue compilation, c'est que chaque fichier source peut être lancé à tout moment (en fonction de là où j'en suis dans mon développement) pour tester ses fonctionnalités ou son comportement exact, ou encore pour diagnostic. Typiquement (c'est une vision schématique), chacun de mes fichiers se termine par qq ch du genre:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    void test_xxx () { ... }
    void test_yyy () { ... }
    void test_zzz () { ... }
    void test () {
       // "hors-commenter" ce que je ne teste pas là maintenant
       test_xxx () ;
       test_yyy () ;
       test_zzz :
    }
    // "hors-commenter" pour inclusion par un autre fichier source
    void main () {
       test () ;
       exit (1) ;
    }
    Il me semble que les outils genre makefile sont faits pour tout autre chose. En gros, pour moi, ils serviraient plutôt à distribuer le code en préparant la compilation par l'usager (utilisateur final ou autre programmeur) de l'application complète (ou du composant logiciel complet). Mais je me trompe peut-être totalement, peut-être que les makefiles sont tout-à-fait capables de permettre de programmer à ma façon.
    Sinon, je suis prêt à écrire des outils moi-même. Par exemple, un bout de code qui lirait les #include dans les en-têtes de mes fichiers source, récursivement, en les cherchant dans une arborescence locale, pour éditer un fichier batch de compilation / édition de liens / exécution test.
    Quelle méthode recommanderiez-vous?

    2 autres points que j'ai en-tête d'explorer sont:
    * Les différents type de fichiers à inclure prédéfinis par C ou par les outils C, et notamment pourquoi/comment l'éditeur de liens trouve les libs standards, et le sens concret de cette différence de syntaxe d'inclusion (<...> ou "...").
    * Le(s) bon(s) usage(s) d'un makefile.

    PS: J'ai dans l'idée de retracer ce fil de discussion pour un tutoriel sur le(s) sujet(s). Qu'en pensez-vous?

    Merci à tous,
    Denis

  2. #2
    Membre Expert
    Avatar de kwariz
    Homme Profil pro
    Chef de projet en SSII
    Inscrit en
    Octobre 2011
    Messages
    898
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Chef de projet en SSII
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2011
    Messages : 898
    Par défaut
    Salut,

    tout d'abord, il y a déjà un cours disponible sur la compilation séparée sur dvp : http://melem.developpez.com/tutoriel...ation-separee/, et un autre sur makefile http://gl.developpez.com/tutoriel/outil/makefile/.

    Sinon, il faut bien te familiariser avec la processus de "j'ai une collection de sources c" pour arriver à "j'ai un exécutable". Cela peut être aussi simple que "gcc -o monprog monprog.c" que plus complexe et caché comme "configure && make" ou cliquer sur l'option Build du menu Project de ton IDE préféré. Mais quelle que soit la méthode, ce qui se passe derrière est toujours identique et en très gros se passe ainsi :

    * tu crées un fichier source ".c"
    * le préprocesseur applique des modifications à ton fichier source, il inclut tous les fichiers des #include {la différence entre <> et "" ainsi que les différentes options disponibles en ligne de commande (-I -idirafter .... ) sont expliquées dans la doc http://gcc.gnu.org/onlinedocs/cpp/ }, il remplace texto les #define, évalue les #if et cie et produit un fichier qu'il passe au compilateur.
    * le compilateur fait le gros du boulot (?), il traduit le code source préprocessé en quelque chose qui sera utilisable par l'éditeur de lien : le fichier objet ".o". Les options sont décrites dans la doc (immense) de gcc par exemple http://gcc.gnu.org/onlinedocs/gcc-4.6.3/gcc/.
    * le linker/éditeur de liens (http://sourceware.org/binutils/docs/ld/) lui se charge de prendre plusieurs fichiers objets, de vérifier que tout ce qui est appelé est bien défini ou dans un ".o" ou dans une bibliothèque statique ".a" ou un bibliothèque dynamique ".so" et crée un fichier exécutable.

    Tout ça est caché derrière un frontend : gcc.

    Ensuite :

    * le loader charge l'exécutable, vérifie les liaisons dynamiques, et lance l'exécution qui commence par l'initialisation de la libc pour le programme, puis l'appel à main.

    Cela dit, il faut voir l'approche modulaire du c "simplement" :

    un source ".c" est une collection de fonctions qui ont un lien logique entre elles. Par exemple liste.c contiendra toutes les fonctions de gestion d'une liste.

    un header ".h" regroupe toutes (et normalement uniquement) les définitions nécessaires pour pouvoir utiliser la/les fonctionnalité(s) proposées pour le ".c". liste.h fournira la définition d'un type liste_t, de fonction permettant la manipulation d'une liste, mais cachera des fonctions uniquement utiles en interne à liste.c (par exemple la définition et la déclaration de tout ce qui concerne les noeuds).

    Tu peux voir ça comme un équivalent de l'objet liste est implémenté dans le .c et son interface est définie dans le .h

    Inclure un .h dans un source ne fait donc qu'inclure des définitions, pas l'implémentation qui elle se trouve sous forme de source dans le .c et sous forme compilée dans le .o
    C'est pourquoi à l'édition des liens pour créer un exécutable il faut fournir toutes les implémentations (=tous les .c ou tous les .o).

    Il existe donc des dépendances entre les différents fichiers. Ces dépendances sont décrites dans un Makefile. Par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    monprog: monprog.o liste.o
      <la/les commandes pour lier monprog.o et liste.o>
     
    monprog.o: monprog.c liste.h
      <la/les commandes pour compiler monprog.c>
     
    liste.o: liste.c liste.h
      <la/les commandes pour compiler liste.c>
    Tu dis en substance que :
    pour créer l'exécutable monprog il te faut deux modules : monprog.o et liste.o
    monprog.o dépend de monprog.c (en effet si tu modifies ton source tu dois recompiler) et liste.h (si l'interface est modifiée alors tu dois recompiler aussi)
    liste.o dépend de liste.c (bah oui, l'implémentation) et de liste.h (l'interface)

    L'idée est que si tu ne modifies que ton source monprog.c, tu ne vas devoir recompiler (=produire un .o) liste.c puisque tout y est encore valable (l'interface n'a pas changée) : gain de temps (entre autre). Makefile se base sur les heures de modifications des fichiers. D'autres outils sont plus développés ou mieux adapté à d'autres environnements. Makefile est très puissant mais très vieux aussi

    Il existe également une option gcc qui permet de générer ces dépendances. Tu peux jeter sur le makefile "générique" que j'utilise pour de petits projets one-shot (Générateur de combinaisons), tu pose le Makefile dans un répertoire, tu mets tes sources dans un répertoire src, tu tunes un peu le Makefile (les libs et options de compil) et tout le reste est géré tant que la complexité du projet n'est pas trop grande.

  3. #3
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Chercheur d'emploi
    Inscrit en
    Septembre 2007
    Messages
    7 480
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur d'emploi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 480
    Par défaut
    Bonjour,

    Tes suppositions initiales sont les bonnes. L'usage veut que que les fichiers objets produit par le compilateur soit associés à des fichiers *.c et que les *.h ne servent qu'aux déclarations.

    Par contre, il te faut savoir que le compilateur ne fait pas en soi le distingo entre les différents types de fichiers : tu peux inclure en cascade n'importe quel fichier et il essaiera d'en compiler le contenu en continu comme s'il s'agissait d'un flux unique.


    1. Pour répondre à une de tes questions, il est tout-à-fait normal qu'un fichier *.c importe ses propres déclarations car, dedans, on peut y trouver :

    • Les prototypes de fonctions ;
    • Les macros #define qui servent autant au code proprement dit qu'à celui qui va l'utiliser ;
    • Les déclarations de variables globales externes ;
    • Les définitions de types, comme les unions, les structures et les typedef associés.


    Les #define peuvent servir à fixer les constantes d'un programme. Par exemple, si tu utilises un buffer de taille fixe, il est normal que l'utilisateur connaisse sa taille, mais le programme lui-même doit aussi en être informé à la compil. S'il s'avère à l'usage qu'il est trop petit, il te suffit de modifier la ligne #define en question dans le *.h et de recompiler le tout pour régler le problème.


    2. Par ailleurs, comme dit plus haut, le code C compilé est censé être vu comme un flux unique. Ça veut dire que si tu utilises une fonction qui n'est défini que plus loin, le compilateur doit être averti à l'avance de son existence ! Les compilateurs modernes (enfin, ceux qui ont moins de 25 ans :-) sont tous capables de supposer d'eux-mêmes que cette fonction va effectivement être définie et de compiler en silence, quitte à relire le fichier une seconde fois… si c'est possible ! Ça ne l'est pas si le fichier provient d'une bande ou d'une tube.

    La solution consiste donc à mettre tous les prototypes de fonction en début de fichier pour ne pas être embêté et le plus simple pour faire cela, encore une fois, consiste à inclure son propre *.h

    3. Si tu mélanges C et C++, ce qui est assez fréquent quand on débute, alors il est possible que tu sois tombé sur du code template. Ça, c'est une des raisons qui peuvent effectivement pousser un codeur à mettre du véritable code dans un fichier *.h. Dans ce cas, il vaut mieux que ce soit explicitement indiqué, et bien séparé du reste.

  4. #4
    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 on fait toujours de la compilation séparée en pratique : même en n'ayant écrit qu'un seul fichier source, l'éditeur de liens aura besoin des modules de bibliothèque qui ont déjà été compilés pour nous. Composer son programme à partir de plusieurs unités de compilation (un module .c et (éventuellement) son .h associé) ne fait qu'utiliser ce principe à notre bénéfice.

    1* Que doit contenir le .c :
    - le code des fonctions. Si les fonctions sont à usage purement interne au module elles seront déclarées static (les fonctions sont extern par défaut)
    - la définition de variables globales (si il y en a)
    - des définitions de type de données ou de constantes à usage purement interne au module
    - On incluera aussi le .h associé (si il existe) pour assurer la cohérence de l'unité de compilation.
    - des include de .h , uniquement ceux qui correspondent au contenu du .c
    - il n'a pas normalement à inclure d'autres .c

    2* Que doit contenir le .h associé :
    - Le prototype des fonctions définies dans le .c et utilisables dans d'autres unités de compilation
    - des déclarations extern de celles des variables globales définies dans le .c qui sont susceptibles d'être utilisées par d'autres unités de compilation
    - des définitions de type de données ou de constantes susceptibles d'être utilisées par d'autres unités de compilation
    - des include de .h, uniquement ceux qui sont correspondent au contenu du .h
    - Il ne doit PAS contenir de définition de variables (parce qu'il a vocation à être inclus dans plusieurs autres unité de compilation ce qui aboutirait à de multiples définitions).

    Le programme exécutable est alors obtenu en deux étapes :

    - Chaque unité du programme est compilée indépendamment des autres. Après compilation, il reste des symboles non résolus (fonctions ou variables globales définies dans une autre unité...)

    - L'éditeur de liens (link editor) est chargé ensuite de composer tous les modules et ceux des bibliothèques utilisées. Il fait les liaisons entre les symboles non résolus et leur emplacement dans le code. A ce stade, il faut spécifier tout ce dont a besoin le programme (explicitement ou par défaut) sinon on se retrouvera avec des symboles non résolus (les include dans le programme ne peuvent le faire par défaut : ils ne font qu'une inclusion de fichier).

  5. #5
    Membre confirmé
    Profil pro
    amateur
    Inscrit en
    Avril 2012
    Messages
    145
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : amateur
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Avril 2012
    Messages : 145
    Par défaut double inclusion de fichier header
    Merci pour toutes vos réponses, ça clarifie bien les choses.

    Alors, j'ai toujours pas compris comment éviter d'inclure plusieurs fois un fichier .h. 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
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    // prog.c
    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    #include "circ.h"
     
    int main () {
       const float MAX_R = 999.9 ;
       srand (time (NULL)) ;
       float r = rand () * MAX_R / RAND_MAX ;
       float c = circ (r) ;
       printf ("rayon %.3f --> circonférence %.3f\n", r, c) ;
       return 1 ;
    }
     
    //salut.c
    #include <stdio.h>
    #include "circ.h"
     
    float circ (float r) {
       return TAU * r ;
    }
     
    // salut.h
    #ifndef H_SALUT
    #define H_SALUT
    const float TAU = 6.28 ;   // voir http://tauday.com/tau-manifesto ;-)
    float circ (float rayon) ;
    #endif
    Une fois les 3 fichiers compilés séparément, prog.c et circ.c incluent tous deux le code de circ.h. Il me semble que c'est nécessaire, puisque prog.c doit avoir la déclaration de la fonction circ() et circ.c doit avoir celle de TAU. Correct?
    Donc forcément, lorsque l'on relie tout ça, ça donne des erreurs. Voilà ma commande et son résultat:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    spir@ospir:~/prog/C/comp$ gcc -Wall -o prog prog.o circ.o
    circ.o:(.rodata+0x0): multiple definition of `TAU'
    prog.o:(.rodata+0x0): first defined here
    collect2: ld returned 1 exit status
    Bon, je concède que l'exemple est un peu artificiel, car ici TAU n'a pas besoin d'être exporté, donc il pourrait être dans circ.c. Mais imaginons... De toute façon, le cas général n'est-il pas que la code client (ici prog) inclue le header de son "fournisseur" (circ.h), et le fichier source .c de ce module (circ.c) inclue aussi ce même header ?

    Il y a un point qui m'échappe.

    EDIT: Les tutoriels sur la compil séparée et sur makefile ne m'aide, car dans aucun des deux le fichier source .c du "module" n'inclue son header.

    denis

  6. #6
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Chercheur d'emploi
    Inscrit en
    Septembre 2007
    Messages
    7 480
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur d'emploi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 480
    Par défaut
    Bonjour,

    Citation Envoyé par denispir Voir le message

    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
    // prog.c
    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    #include "circ.h"
    
    int main () {
       const float MAX_R = 999.9 ;
       srand (time (NULL)) ;
       float r = rand () * MAX_R / RAND_MAX ;
       float c = circ (r) ;
       printf ("rayon %.3f --> circonférence %.3f\n", r, c) ;
       return 1 ;
    }
    
    //salut.c
    #include <stdio.h>
    #include "circ.h"
    
    float circ (float r) {
       return TAU * r ;
    }
    
    // salut.h
    #ifndef H_SALUT
    #define H_SALUT
    extern const float TAU;   // voir http://tauday.com/tau-manifesto ;-)
    float circ (float rayon) ;
    #endif
    Il faut ajouter « extern » à l'endroit indiqué (et virer l'initialisation avec « = »).

    Comme on l'a dit plus haut, le compilateur interprète le code source provenant des différents fichiers inclus comme un flot continu sans se soucier des fichiers eux-mêmes.

    Lorsque tu écris « const float TAU = », ce n'est pas une directive à l'intention du compilateur que tu rédiges (utiliser #define pour cela), mais c'est une variable globale que tu instancies et qui a une adresse en mémoire. « extern » sert justement à indiquer qu'une variable globale existe quelque part sans l'instancier. C'est un peu l'équivalent du prototype pour une fonction.

    Donc, tu fais une déclaration « extern » dans ton fichier *.h qui sera lue par tout le monde et tu instancies ta variable comme tu l'as fait mais dans un et un seul fichier *.c.

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

Discussions similaires

  1. compilation de programme multi-modules
    Par denispir dans le forum Débuter
    Réponses: 14
    Dernier message: 15/04/2012, 13h13
  2. [langage] compiler un prog perl
    Par mike21 dans le forum Langage
    Réponses: 20
    Dernier message: 23/11/2004, 17h57
  3. Comment compiler un prog Gtk sous Debian ?
    Par GLDavid dans le forum GTK+
    Réponses: 3
    Dernier message: 25/06/2004, 19h49
  4. compiler un prog open gl
    Par bobbyf dans le forum OpenGL
    Réponses: 2
    Dernier message: 11/03/2004, 08h22
  5. [TP]Compiler un prog sans entrer dans TP7
    Par poppels dans le forum Turbo Pascal
    Réponses: 11
    Dernier message: 23/10/2002, 18h46

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