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 relation entre sa déclaration et sa définition


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Homme Profil pro
    Assistant aux utilisateurs
    Inscrit en
    Décembre 2011
    Messages
    61
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Assistant aux utilisateurs
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Décembre 2011
    Messages : 61
    Par défaut compilation relation entre sa déclaration et sa définition
    Bonjour,
    le titre est peut être mal choisi... voilà sur le tutoriel http://emmanuel-delahaye.developpez.com/tutoriels/c/bonnes-pratiques-codage-c/
    il y a une vidéo et je me demandais à quelle étape de la compilation le compilateur sait que la fonction définit dans hello.h se trouve dans hello.c et quand fait -il le lien entre hello.c et main.c
    http://www.cmi.univ-mrs.fr/~contensi...=env&page=comp et http://melem.developpez.com/tutoriel...ation-separee/ ne m'ont rien appris. Pourriez vous m'expliquer?
    Merci

  2. #2
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Chercheur d'emploi
    Inscrit en
    Septembre 2007
    Messages
    7 485
    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 485
    Par défaut
    Bonjour,

    L'intérêt est de pouvoir séparer les unités de compilation pour éviter d'avoir à recompiler le projet entier à chaque fois que tu modifies un seul fichier, mais également de te permettre d'utiliser du code ou des ressources déjà compilées sans forcément disposer du code source.

    C'est vrai au sein d'un projet mais c'est exactement le même procédé qui est mis en œuvre lorsque ton programme fait appel à une bibliothèque du système d'exploitation, par exemple. Celle-ci est déjà compilée depuis belle lurette, et heureusement. L'avantage, c'est que tu n'as pas besoin de savoir comment une fonction est écrite pour l'utiliser. Tout ce qu'il te faut, c'est en quelque sorte le « mode d'emploi », c'est-à-dire la façon dont il faut l'appeler : son nom, ses arguments avec leurs types et le type de la valeur de retour. Donc, la déclaration seule suffit à permettre au compilateur de générer du code valide en laissant simplement « en blanc » l'adresse de la fonction à appeler. C'est ensuite le rôle du linker ou « éditeur de liens » de rassembler tous les fichiers objets entre eux et de remplir les blancs des uns avec les adresses des symboles trouvés dans les autres.

    Tu peux voir cela comme un avionneur qui construit généralement l'appareil entier mais qui laisse le soin à un motoriste de construire ses moteurs. La seule chose que l'un et l'autre ont besoin de faire est de se mettre d'accord à l'avance sur la forme et l'emplacement des trous qui serviront à passer les boulons qui les relieront les uns à l'autre. Cette partie commune située exactement entre les deux pièces et servant à les adapter l'une à l'autre s'appelle une interface, et on utilise le même mot en programmation.

    Par ailleurs, même au sein d'une même unité de compilation, les déclarations se retrouvent souvent regroupées en tête de fichiers car cela évite d'avoir à imposer un ordre de définition et c'est même nécessaire en cas de référence croisée, lorsque A se réfère à B et que B se réfère également à A. Il est donc nécessaire de les déclarer toutes les deux à l'avance, et de définir l'une puis l'autre.

    Par conséquent, le plus naturel et le plus efficace consiste à rassembler toutes ces déclarations dans un même fichier *.h (pour « headers ») et de l'inclure à la fois au début de l'unité de compilation elle-même et dans toutes celles qui feraient appel aux ressources fournies par la première. Ce fichier *.h peut alors en plus servir de manifeste, en faisant la liste de ce que l'on y trouve.

  3. #3
    Membre confirmé
    Homme Profil pro
    Assistant aux utilisateurs
    Inscrit en
    Décembre 2011
    Messages
    61
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Assistant aux utilisateurs
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Décembre 2011
    Messages : 61
    Par défaut
    alors main.c, hello.c et hello.h sont compilés séparément et c'est l'éditeur de liens qui va "reconnaître" que hello.c contient les fonctions décrite dans hello.h? Si c'est le cas quand on compile seulement main.c comment l'éditeur de lien fait pour "remplir les blancs", il faut le préciser qqpart? Comment il fait je veux dire c'est de la simple comparaison où c'est plus que ça ?
    Merci

  4. #4
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 835
    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 835
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Spirale21 Voir le message
    alors main.c, hello.c et hello.h sont compilés séparément
    Salut
    C'est exact (un bémol toutefois avec hello.h qui ne sera pas compilé mais inclu dans les différents .c qui font appels à lui)

    Citation Envoyé par Spirale21 Voir le message
    et c'est l'éditeur de liens qui va "reconnaître" que hello.c contient les fonctions décrite dans hello.h?
    Non. C'est l'éditeur de liens qui va "reconnaitre" que les fonctions appelées dans les différents sources se trouvent dans main.c ou hello.c

    Citation Envoyé par Spirale21 Voir le message
    Si c'est le cas quand on compile seulement main.c comment l'éditeur de lien fait pour "remplir les blancs", il faut le préciser qqpart?
    La compilation phase 1 ne fait que regarder la syntaxe et les variables. Si main.c appelle une fonction dont le code n'est pas encore connu, cette fonction est "mise à part". Cette phase produit ce qu'on nomme des "modules objets" (les ".o").
    Lors de l'édition de liens (compilation phase 2), les différents modules objets sont rassemblés (avec éventuellement des librairies en plus) et les liens entre les différentes fonctions sont alors résolus...
    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 Obsidian
    Homme Profil pro
    Chercheur d'emploi
    Inscrit en
    Septembre 2007
    Messages
    7 485
    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 485
    Par défaut
    En plus des informations données par Sve@r, retiens simplement que le compilateur lui-même ne fait aucune différence entre *.c et *.h. C'est simplement une convention de nommage.

    Quelque soit son extension, ton compilateur va essayer de traduire ce qu'il lit dans le fichier que tu lui as fourni. Et lorsqu'il rencontre #include, il insère littéralement le contenu du fichier spécifié à l'endroit où se trouve la ligne en question. Si tu essaies d'inclure un fichier binaire par accident par exemple, le compilateur va essayer de le faire quand même. Il en résultera bien sûr une série d'erreurs en cascade, mais le principe est là. Il n'y a pas de contrôle plus poussé a priori (après, tu peux toujours avoir un compilateur un peu plus intelligent qui comprenne ce que tu es en train de faire et qui t'affiche des messages d'avertissement).

    « *.c » et « *.h » sont donc des moyens d'organiser ton code proprement. L'usage veut également qu'on ne compile que les *.c (par exemple lorsque tu utilises un Makefile). Ce sont ces fichiers sources qui vont inclure les *.h dont ils ont besoin, mais ces *.h ne contiendront en principe que les informations nécessaires au bon déroulement de la suite.

    À dire vrai, les #include vont être résolus lors de la précompilation. Passée cette étape, le compilateur ne se souviendra même plus qu'il s'agit de deux fichiers différents.

    Si c'est le cas quand on compile seulement main.c comment l'éditeur de lien fait pour "remplir les blancs", il faut le préciser qqpart? Comment il fait je veux dire c'est de la simple comparaison où c'est plus que ça ?
    Merci
    En temps normal, l'éditeur de liens est appelé directement par le compilateur, donc tu n'as pas à t'en soucier. Ce sera transparent.

    Lorsque tu produis un fichier objet, il est effectivement doté d'une table des symboles qui reprend tout ce qui était visible au niveau global, donc les fonctions et les variables globales, sauf indication contraire (fonctions static). Tu peux t'en servir pour savoir ce qu'il y a à l'intérieur de ce fichier. C'est cette table que le linker va exploiter.

    S'il trouve, pas de problème. S'il ne trouve pas, il laisse en blanc ce qu'il n'a pas réussi à résoudre (le symbole concerné prend un statut spécial). Ça n'empêche pas de consigner dans le fichier objet tout ce qu'il a réussi à compiler.

    S'il ne trouve pas mais que tu lui as explicitement demandé de produire un exécutable, là, il a un problème. Il est évident qu'il ne peut pas finaliser la chose s'il manque des pièces. C'est alors que tu obtiendras le fameux message « Undefined reference to… » ou « Référence indéfinie vers… » telle ou telle fonction. Tu sauras alors qu'il te manque une bibliothèque, ou que tu as oublié de l'ajouter aux flags de ton projet.

  6. #6
    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 : 38
    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
    De belles explications de mes camarades

    Il faut juste préciser car c'est important pour la compréhension qu'on fait souvent un abus de langage avec le mot "compiler". On dit "je compile mon programme" ou "je compile mes fichiers sources pour faire un programme". Il faut être conscient qu'il y a d'abord le passage du pré processeur, qui s'occupe de toutes les inclusions, des macro, etc. Ensuite il y a la vraie compilation qui transforme les fichiers issus du pré processeur en fichier objets et enfin l'éditeur des liens crée le programme en assemblant les fichiers objets (et les éventuelles bibliothèques). Ces étapes sont souvent cachées car on appelle simplement gcc qui se charge de faire ces étapes pour nous.

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

Discussions similaires

  1. [EJBQL] [CMP] Relation entre deux beans
    Par salome dans le forum Java EE
    Réponses: 1
    Dernier message: 11/07/2005, 23h50
  2. Relation entre les tables
    Par adelyx dans le forum Bases de données
    Réponses: 1
    Dernier message: 02/04/2005, 23h06
  3. Relation entre deux tables
    Par manel007 dans le forum Langage SQL
    Réponses: 5
    Dernier message: 04/03/2005, 16h54
  4. Relations entre les Paquetages
    Par bran_noz dans le forum UML
    Réponses: 4
    Dernier message: 25/06/2004, 14h05
  5. [Relations] afficher les relations entre 2 tables
    Par dzincou dans le forum PostgreSQL
    Réponses: 5
    Dernier message: 14/01/2004, 17h07

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