Partage
  • Partager sur Facebook
  • Partager sur Twitter

#include et linker

Comment main.c va chercher les fonctions dans vehicule.c ?

    19 janvier 2021 à 17:21:52

    Bonjour à tous,

    je poste pour vous demander de l'aide concernant la comprehension de la programmation modulaire:

    J'ai 3 fichier: main.c, voiture.c et voiture.h.

    J'ai bien compris qu'il fallait utiliser le header voiture.h dans main.c et voiture.c.

    Cependant, je ne comprends pas pourquoi. De ce qui est expliqué, le but de la directive #include est d'inclure en haut des fichier .c le header voiture.h.

    Alors pourquoi ne pas inclure directement voiture.c dans main.c (c'est à dire #include voiture.c dans main.c)? Surement une histoire d'optimisation de l'espace me direz vous.

    Et pourquoi voiture.c a besoin d'inclure voiture.h alors qu'il définit lui même les fonctions utilisés.

    Est-ce que le linker à un rapport ?

    En fait la vraie question c'est COMMENT ca fonctionne concretement? Je sais qu'en informatique on dit souvent "Ca marche donc c'est bon", mais je ne me vois pas copié/coller un fichier .h à chaque fois que je croise un .c sans comprendre.

    Je vous remercie d'avance pour vos réponses et vos précisions.

    • Partager sur Facebook
    • Partager sur Twitter
      19 janvier 2021 à 18:18:06

      D'abord, tu n'as pas besoin du fichier voiture.h dans voiture.c à moins que ce fichier .h contiennes des définitions nécessaires aux deux modules.
      Quand on fait de la programmation modulaire, c'est pour séparer les fichiers.
      Le "linker" n'a pas vraiment quelque chose à voir de ce côté.
      Je ne sais pas si tu utilises un IDE, mais tu devras dire au compilateur qu'il doit inclure dans la compilation les fichiers main.c et voiture.c.
      • Partager sur Facebook
      • Partager sur Twitter

      Le Tout est souvent plus grand que la somme de ses parties.

        19 janvier 2021 à 18:26:48

        Silverlight_X a écrit:

        Bonjour à tous,

        je poste pour vous demander de l'aide concernant la comprehension de la programmation modulaire:

        J'ai 3 fichier: main.c, voiture.c et voiture.h.

        J'ai bien compris qu'il fallait utiliser le header voiture.h dans main.c et voiture.c.

        Cependant, je ne comprends pas pourquoi. De ce qui est expliqué, le but de la directive #include est d'inclure en haut des fichier .c le header voiture.h.

        Hello,

        une directive include inclut le fichier passé en paramètre là où elle est placée, pas forcément en haut.

        Silverlight_X a écrit:

        Alors pourquoi ne pas inclure directement voiture.c dans main.c (c'est à dire #include voiture.c dans main.c)? Surement une histoire d'optimisation de l'espace me direz vous.

        [...]

        Est-ce que le linker à un rapport ?

        En fait la vraie question c'est COMMENT ca fonctionne concretement?

        C'est une histoire de compilation séparée : on crée plusieurs fichiers source (.c) pour pouvoir les compiler séparément et en faire des fichiers objets (.o). C'est la phase de compilation.
        Ensuite on prend plusieurs fichiers objets (.o) pour en faire ou un exécutable ou une bibliothèque dynamique, c'ets la phase d'édition des liens faites par le linker.

        Voilà en très très gros comment ça se passe (parce qu'il y a d'autres phases).

        Donc oui, tu pourrais inclure plein de .c dans le main.c mais à chaque petite modif tu seras obligé de tout recompiler, alors qu'avec la compilation séparée tu ne recompile que ce que tu as modifié.

        Silverlight_X a écrit:

        Et pourquoi voiture.c a besoin d'inclure voiture.h alors qu'il définit lui même les fonctions utilisés.

        Parce qu'il y a une différence entre la déclaration et la définition. Par exemple pour pouvoir appeler correctement une fonction, le compilateur a besoin de connaitre au moment de l'appel le nombre et le type des paramètres ainsi que le type de la valeur de retour. Une simple déclaration suffit pour cela :

        // foo est une fonction qui prend 2 paramètres un entier et un pointeur sur char et qui renvoie un flottant 
        double foo(int, char *);

        Une fois déclarée tu peux l'utiliser sans même en connaître le code qui lui sera dans une autre unité de compilation (un autre source). Mais pour savoir ce que propose une unité de compilation il faut un header qui regroupe toutes les déclarations → c'est le .h

        La définition de la fonction sera quant à elle dans le fichier source.



        • Partager sur Facebook
        • Partager sur Twitter
          20 janvier 2021 à 1:50:08

          Alors, pourquoi mettre voiture.h dans voiture.c s'il n'y a que la déclaration dans le fichier .h?
          voiture.h pourrait contenir des définitions de symboles nécessaires à toutes les fonctions du projet.
          Ou bien, il pourrait y avoir un include dans voiture.h d'un autre fichier .h
          • Partager sur Facebook
          • Partager sur Twitter

          Le Tout est souvent plus grand que la somme de ses parties.

            20 janvier 2021 à 9:45:00

            C'est une bonne pratique d'inclure son entête lié au fichier source. Ça évite les erreurs stupides en cas de changement de signature.

            Exemple si dans voiture.h j'ai cette fonction :

            bool
            voiture_demarrer(void);

            Alors que dans voiture.c j'ai cette fonction (et que j'inclue pas voiture.h)

            void
            voiture_demarrer(void) {}

            Et bien je respecte pas mon ABI. J'ai déclaré une fonction retournant un bool alors que dans le TU de voiture.c je ne retourne rien, du coup il peut se passer n'importe quoi au niveau de l'appelant qui croit que la fonction va renvoyer un bool alors qu'elle renvoie rien. En revanche, si tu inclues voiture.h dans voiture.c tu auras le droit à une erreur du style "mismatch declaration" car en C il est interdit de redéclarer une fonction sous un autre prototype que l'original.


            -
            Edité par markand 20 janvier 2021 à 9:45:56

            • Partager sur Facebook
            • Partager sur Twitter

            git is great because Linus did it, mercurial is better because he didn't.

              20 janvier 2021 à 21:25:08

              Ceci devrait t'intéresser: https://en.wikipedia.org/wiki/One_Definition_Rule

              Si tu inclus des .c dans d'autres .c, tu violes cette règle, car une définition va se retrouver dans plusieurs unités de compilation.

              Le compilateur ne te dira rien, il va manger tout ça comme du petit lait. Par contre l'éditeur de liens te ramènera à la réalité.

              -
              Edité par SpaceIn 20 janvier 2021 à 21:27:37

              • Partager sur Facebook
              • Partager sur Twitter

              #include et linker

              × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
              × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
              • Editeur
              • Markdown