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 :

La compilation séparée en C [Tutoriel]


Sujet :

C

  1. #1
    Expert éminent
    Avatar de Melem
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2006
    Messages
    3 656
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Janvier 2006
    Messages : 3 656
    Points : 8 389
    Points
    8 389
    Par défaut La compilation séparée en C
    Tutoriel : La compilation séparée en C
    La compilation séparée désigne le fait de compiler plusieurs fichiers sources séparément puis de les lier ensuite pour générer le produit final qui peut être un exécutable par exemple. Elle comprend plusieurs techniques que nous allons explorer tout au long de ce tutoriel.
    A vos commentaires !

  2. #2
    Membre actif
    Homme Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Décembre 2003
    Messages
    217
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2003
    Messages : 217
    Points : 242
    Points
    242
    Par défaut
    Bonjour,

    Je trouve quelques limites à ce tutoriel qui pour l'instant me rebutent à le conseiller à ceux qui veulent s'initier à la compilation séparée.

    Dans ce tutoriel, les fichiers d'entête sont presque abordés à la va-vite, alors que c'est un point majeur de la compilation séparée. Pour preuve, les exemples des sections II-A et II-D reprennent la mauvaise pratique de placer les déclarations de fonctions dans les .c les utilisant, alors que cet exemple typique n'apparait jamais :

    dsomme.c :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    #include "dsomme.h"
     
    int somme(int a, int b)
    {
        return a + b;
    }
    dsomme.h :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    extern int somme(int a, int b);
    exemple.c :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    #include <stdio.h>
    #include <dsomme.h>
     
    int main()
    {
        int a = 2, b = 5;
     
        printf("%d + %d = %d\n", a, b, somme(a, b));
        printf("%d * %d = %d\n", a, b, produit(a, b));
     
        return 0;
    }
    Après peut être que le fait de placer les déclarations dans un .c est une windowserie (je ne connais pas assez Windows), mais cela m'étonnerait.


    Enfin idéalement, on pourrait introduire aussi les Makefile, pour les UNIXiens, mais c'est plus avancé je le concède.


    En espérant avoir apporté été constructif.

    Cordialement.

  3. #3
    Expert éminent
    Avatar de Melem
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2006
    Messages
    3 656
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Janvier 2006
    Messages : 3 656
    Points : 8 389
    Points
    8 389
    Par défaut
    Je ne partage ton avis sur l'utilisation des fichiers d'en-tête, et ça n'a rien à voir avec le système. C'est juste une différence de style de codage. Personnellement, je trouve qu'il est avantageux d'utiliser un fichier d'en-tête quand il y a beaucoup de déclarations ou quand une déclaration risque d'être utilisée dans plusieurs projets ou dans plusiers fichiers sources mais pas quand on veut juste déclarer une fonction externe dans un fichier source d'un projet.

    D'autre part, je pense avoir correctement introduit l'utilité et la manière d'utiliser les fichiers d'en-tête, justement parce que je suis parti d'un projet qui ne s'en servait pas. Je permets ainsi au lecteur d'assister en direct à la transformation d'un projet mal conçu en un projet correctement conçu.

    Enfin idéalement, on pourrait introduire aussi les Makefile, pour les UNIXiens, mais c'est plus avancé je le concède.
    "Make" peut aussi être utilisé sous Windows bien qu'il existe d'autres solutions plus avancées comme msbuild par exemple, mais les développeurs préfèrent de toute façon utiliser un EDI plutôt qu'un logiciel en ligne de commandes. Ainsi, pour alléger le tutoriel, j'ai opté pour la solution EDI - la plus simple - plutôt que de présenter 1000 façons d'arriver au même résultat. Mais c'est vrai que du coup j'étais pas très sympa envers les unixiens .

  4. #4
    Membre du Club
    Profil pro
    Inscrit en
    Février 2010
    Messages
    87
    Détails du profil
    Informations personnelles :
    Localisation : Algérie

    Informations forums :
    Inscription : Février 2010
    Messages : 87
    Points : 62
    Points
    62
    Par défaut ())))))))
    merci pour le tout

  5. #5
    Membre confirmé
    Inscrit en
    Juillet 2005
    Messages
    512
    Détails du profil
    Informations forums :
    Inscription : Juillet 2005
    Messages : 512
    Points : 641
    Points
    641
    Par défaut
    Nous allons créer un programme qui affiche la somme et la différence de deux nombres...

  6. #6
    Expert éminent
    Avatar de Melem
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2006
    Messages
    3 656
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Janvier 2006
    Messages : 3 656
    Points : 8 389
    Points
    8 389
    Par défaut
    Citation Envoyé par PIC16F877A
    merci pour le tout
    Content pour toi .
    Lucien63 : Merci.

  7. #7
    Membre expérimenté
    Profil pro
    Développeur en systèmes embarqués retraité
    Inscrit en
    Mars 2006
    Messages
    946
    Détails du profil
    Informations personnelles :
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Mars 2006
    Messages : 946
    Points : 1 351
    Points
    1 351
    Par défaut
    Citation Envoyé par Sékiltoyai Voir le message
    la mauvaise pratique de placer les déclarations de fonctions dans les .c les utilisant
    Peux tu développer? Il me semble que si des fonctions, des variables ou des structures doivent être opaques, il est normal de les déclarer dans le fichier C. Les déclarer dans le fichier h, c'est donner l'accès à tous et augmenter la portée de ces objets.

    @Melem j'aime bien, je trouve juste un peu dommage que tu aies choisi un IDE au départ (codeblocks) pour passer sur un autre (MS Visual Studio .NET) au chapitre des bibliothèques.

    A+

    Pfeuh

  8. #8
    Expert éminent
    Avatar de Melem
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2006
    Messages
    3 656
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Janvier 2006
    Messages : 3 656
    Points : 8 389
    Points
    8 389
    Par défaut
    Citation Envoyé par pfeuh Voir le message
    Peux tu développer? Il me semble que si des fonctions, des variables ou des structures doivent être opaques, il est normal de les déclarer dans le fichier C. Les déclarer dans le fichier h, c'est donner l'accès à tous et augmenter la portée de ces objets.
    Sékiltoyai ne parlait pas des structures opaques, en plus tu sembles encore mélanger "déclaration" et "définition" mais au fond, tu as tout à fait raison.
    Citation Envoyé par pfeuh Voir le message
    @Melem j'aime bien, je trouve juste un peu dommage que tu aies choisi un IDE au départ (codeblocks) pour passer sur un autre (MS Visual Studio .NET) au chapitre des bibliothèques.
    Je me suis dit que dans la partie I, les techniques présentées pouvaient s'appliquer sous n'importe quel système et qu'il serait donc mieux d'utiliser un EDI multiplateforme alors que dans la partie II, il fallait choisir un système et comme j'ai choisi Windows, je suis passé à l'EDI de référence sous Windows à savoir Visual mais c'est tordu en effet . Que dis-tu d'utiliser les deux tout au long du tutoriel ?

  9. #9
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 15
    Points : 17
    Points
    17
    Par défaut
    Citation Envoyé par pfeuh Voir le message
    Peux tu développer? Il me semble que si des fonctions, des variables ou des structures doivent être opaques, il est normal de les déclarer dans le fichier C. Les déclarer dans le fichier h, c'est donner l'accès à tous et augmenter la portée de ces objets.

    @Melem j'aime bien, je trouve juste un peu dommage que tu aies choisi un IDE au départ (codeblocks) pour passer sur un autre (MS Visual Studio .NET) au chapitre des bibliothèques.

    A+

    Pfeuh
    Si on compile le .h, alors le .h n'est pas visible (le .h compile est utilise directement), et la fonction est declaree dans un .h. (apres c'est pas forcement intelligent).

    vu que tu parles d'IDE,

    Citation Envoyé par Melem Voir le message
    (...) mais les développeurs préfèrent de toute façon utiliser un EDI plutôt qu'un logiciel en ligne de commandes. (...)
    je prefere les lignes de commandes qui marchent, a un ide qui plante.


    Sinon par rapport au tutoriel, je comprend pas non plus l'interet de la declarer dans le .c, et c'est peut etre un gout personnel, mais je prefererais voir static devant la fonction elle meme.

    (sinon c'est un bon tutoriel, pour qui utilise windows).

  10. #10
    Membre expérimenté
    Profil pro
    Développeur en systèmes embarqués retraité
    Inscrit en
    Mars 2006
    Messages
    946
    Détails du profil
    Informations personnelles :
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Mars 2006
    Messages : 946
    Points : 1 351
    Points
    1 351
    Par défaut
    Citation Envoyé par Melem Voir le message
    comme j'ai choisi Windows, je suis passé à l'EDI de référence sous Windows à savoir Visual mais c'est tordu en effet
    Vu que codeblocks est multiplateformes, il y a de grandes chances pour que la gestion des librairies soit identique pour tout le monde. Je pense que s'il y a un IDE de référence, c'est bien celui là.

    Citation Envoyé par Erwan-Overseas Voir le message
    Si on compile le .h, alors le .h n'est pas visible (le .h compile est utilise directement), et la fonction est declaree dans un .h. (apres c'est pas forcement intelligent).
    Donc 2 headers à gérer, un pour la compilation et un pour la distribution? C'est une approche que j'ai essayée, mais assez pénible pour la maintenance. Problèmes de synchro entre les 2 headers. C'est vraiment source de bugs durs à cerner.

    Un compromis serait d'appeler le header public par le header qui fabrique la libraire. Comme ça, pas de doublon.

  11. #11
    Expert éminent
    Avatar de Melem
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2006
    Messages
    3 656
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Janvier 2006
    Messages : 3 656
    Points : 8 389
    Points
    8 389
    Par défaut
    Citation Envoyé par Erwan-Overseas
    Si on compile le .h, alors le .h n'est pas visible (le .h compile est utilise directement), et la fonction est declaree dans un .h. (apres c'est pas forcement intelligent).
    Qui compile des .h ?

    Citation Envoyé par Erwan-Overseas
    je prefere les lignes de commandes qui marchent, a un ide qui plante.
    C'est sûr que s'il pante je ne vois pas trop l'intérêt de l'utiliser. Heureusement qu'avec mes 8 ans d'expérience avec les EDIs, je n'ai jamais rencontré ce problème.

    Citation Envoyé par Erwan-Overseas
    Sinon par rapport au tutoriel, je comprend pas non plus l'interet de la declarer dans le .c, et c'est peut etre un gout personnel, mais je prefererais voir static devant la fonction elle meme.
    Dans ce cas, on n'aurait qu'un seul fichier source et ça ne doit pas être le meilleur exemple de mise en oeuvre de la compilation séparée.

    Citation Envoyé par Erwan-Overseas
    sinon c'est un bon tutoriel, pour qui utilise windows
    Merci. Et j'espère que j'ai fait le bon choix en choisissant Windows car l'écrasante majorité des tutoriels et même des livres de C sont déjà orientés unix. Pauvres windowsiens toujours délaissés .

    Citation Envoyé par pfeuh
    Vu que codeblocks est multiplateformes, il y a de grandes chances pour que la gestion des librairies soit identique pour tout le monde. Je pense que s'il y a un IDE de référence, c'est bien celui là.
    Le plus utilisé peut-être ? Je n'en ai aucune idée. Ce qui est sûr par contre c'est que le l'EDI de référence sous Windows, c'est bien Visual .

  12. #12
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 15
    Points : 17
    Points
    17
    Par défaut
    Citation Envoyé par pfeuh Voir le message
    (...)Donc 2 headers à gérer, un pour la compilation et un pour la distribution? C'est une approche que j'ai essayée, mais assez pénible pour la maintenance. Problèmes de synchro entre les 2 headers. C'est vraiment source de bugs durs à cerner.

    Un compromis serait d'appeler le header public par le header qui fabrique la libraire. Comme ça, pas de doublon.
    Je suis d'accord pour dire que c'est sources de probleme, d'autant plus qu'un header compile est souvent d'une taille importante...
    Je n'utilise jamais de header compile.
    Simplement pour dire, que l'on peut declarer dans un .h, et rester opaque.


    @melem:
    la compilation de .h existe (et elle est necessaire), je n'ai pas dit qu'avoir des header precompile soit d'une utilite capitale (je me cite "apres c'est pas forcement intelligent", ce qui ne veut pas dire que ca ne peut pas l'etre).


    Moi en 10 minutes je fais cracher eclipse, np++ et consorts. (j'avou que visual studio n'a jamais crashe, mais je l'utilise si peu), d'une maniere generale, edi, ou simplement sous taches utile au developpement, les lignes de commande, et le travail sur un terminal, offre une foule bien vaste de possibilite, apres les EDI ont leur gros avantages... question de taches, et de gouts.

    "Dans ce cas, on n'aurait qu'un seul fichier source et ça ne doit pas être le meilleur exemple de mise en oeuvre de la compilation séparée."
    je ne dis pas d'utiliser des fonctions static partout, d'ailleurs, c'est pas ce que j'ai di (je ne vais pas me citer... ).
    simplement, si tu connais ton tuto, tu sais que tu as declarer dans un fichier c un prototype de fonction prefixe du mot clef 'static', alors, plutot qu'un prototype local, on peut developper de bas en haut, et mettre le mot clef static devant la fonction plutot que devant le prototype, me semble plus clair (surtout si on supprime le prototype).


    et enfin, je suis d'accord avec toi, ce tutoriel est utile.
    je l'ai di avec moins d'emotion, si je le trouvais inutile, alors apporterais-je d'inutiles commentaires?

  13. #13
    Expert éminent sénior

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

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 603
    Points : 17 913
    Points
    17 913
    Billets dans le blog
    2
    Par défaut
    bin, je vais ajouter mon commentaire...

    • introduction :

      on ne précise pas grand chose d'intéressant... Ce qui serait plus utile serait de signaler qu'un langage comme le C, compilé, n'est pas exécutable directement, et qu'il faut passer par une transformation (bref, expliquer ou pointer vers Wiki pour expliquer ce qu'est la différence entre un fichier d'instructions ASCII, une compilation, et une édition de liens).

    • le projet :

      on arrive de but en blanc sur 2 fichiers.. Pédagogiquement, il serait bon de commencer par un, puis d'expliquer que l'intéressant est de pouvoir séparer les fonctions dans un fichier séparé (avec les diverses raisons : modification, exportation, clarté..). Ce qui donnerait le pourquoi on veut un .h (voir plus bas)

    • Tu donnes la compilation sous CodeBlock. Une compilation sous unixoide (ou cygwin) serait également pédagogiquement un bon exemple, puisqu'on voit chaque étape de la compilation séparément.

    • le mot-clé extern :

      Nous avons déjà résolu le problème pour les fonctions, ne reste donc plus que les variables
      Késako ? D'où ça vient ? On a rien résolu du tout à ce stade, et il n'y a pas d'explication (d'autant plus que tu ne te sers pas d'extern...)

    • le mot-clé static : erreur, puisque tu déclares le protype en static mais pas la fonction...

    • les fichiers d'entête : outre le fait que cela arrive comme un cheveu sur la soupe (voir plus haut), là encore tu ne déclares pas les prototypes comme extern.. Mauvaise pratique...

    • les structures opaques : pourquoi prendre comme exemple ça, qui est compliqué et inutile ? Pourquoi ne pas se servir simplement de FILE, ou de struct tm, et pourquoi parler directement de créateur/destructeur ??? quand on utilise FILE, on n'a ni créateur ni destructeur en tant que tel... Notions inutiles et superflues dans le cadre des types opaques (en outre, Emmanuel Delahaye a fait un excellent chapitre dessus, si tu veux expliquer vraiment réfère-toi à cette partie de son cours).

    • Les bibliothèques :


      • Bibliothèques statiques :

        Une bibliothèque statique (.lib ou .a) est un fichier qui regroupe un ou plusieurs modules objets. Elles s'utilisent donc de la même manière que ces derniers.
        C'est également vrai des bibliothèques dynamiques, et NON elles ne s'utilisent pas de la même manière (il faut les mot-clés spéciaux à l'édition de lien)

        Ces explications seraient à remonter dans "blibliothèques", la seule différence entre statique et dynamqiue étant dans le recopiage du code (donnant un binaire autonome) ou dans l'insertion d'une adresse de jump (donnant un binaire nécessitant la présence runtime de la DLL en question)..

      • bibliothèque dynamqiue :

        mêmes remarques

        Une bibliothèque dynamique est un fichier qui ne sera effectivement lié à l'exécutable que pendant l'exécution
        Ceci est faux (c'est lié à la compil puisqu'on insère l'adresse du début de la fonction)



    • le concept d'API :

      outre le fait que ce chapitre est franchement plus que faible (avec un tel titre) quel est son intérêt dans le cadre des fichiers d'entête si ce n'est simplement d'égaler API avec définition dans le .h ?



    Désolé, mais je trouve pas mal à y redire...
    "Un homme sage ne croit que la moitié de ce qu’il lit. Plus sage encore, il sait laquelle".

    Consultant indépendant.
    Architecture systèmes complexes. Programmation grosses applications critiques. Ergonomie.
    C, Fortran, XWindow/Motif, Java

    Je ne réponds pas aux MP techniques

  14. #14
    Membre éclairé
    Avatar de D[r]eadLock
    Profil pro
    Inscrit en
    Mai 2002
    Messages
    504
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France

    Informations forums :
    Inscription : Mai 2002
    Messages : 504
    Points : 750
    Points
    750
    Par défaut
    Citation Envoyé par Melem Voir le message
    Personnellement, je trouve qu'il est avantageux d'utiliser un fichier d'en-tête quand il y a beaucoup de déclarations ou quand une déclaration risque d'être utilisée dans plusieurs projets ou dans plusiers fichiers sources mais pas quand on veut juste déclarer une fonction externe dans un fichier source d'un projet.
    Je suis plutôt d'accord avec Sékiltoyai. En effet, si tu change le prototype d'une fonction, il faut la changer dans le .c de celui qui appelle la fonction. Ça ne devient "plus" modulaire. Et pire, le compilo peut ne rien voir et générer du code faux (genre somme prend des pointeurs ou une signature différente). Après les compilo windows ajoute peut-être les signatures des fonctions dans les objets, mais pas gcc.
    Exemple:
    Code main.c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    #include <stdio.h>
     
    extern int somme(int a, int b);
     
    int main(void)
    {
            int a = 5;
            int b = 10;
            printf("somme(%d,%d) = %d\n", a, b, somme(a, b));
            return 0;
    }
    Code somme.c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    int somme(int *a, int *b)
    {
            return *a + *b;
    }

    À la compil, aucun warning, rien (sauf si -Wmissing-prototypes, et encore, si on ajoute int somme(int *, int*); (ce qui est "redondant" avec ce qu'il y a dans main.c) ça passe), par contre à l'exécution...

    Pour moi, tout ce qui est accessible dans un objet doit être clairement défini (et donc dans un .h).

  15. #15
    Expert éminent sénior

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

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 603
    Points : 17 913
    Points
    17 913
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par D[r]eadLock Voir le message
    Pour moi, tout ce qui est accessible dans un objet doit être clairement défini (et donc dans un .h).
    absolument, et être déclaré comme extern.

    Toutes les autres doivent être déclarées comme static (ou extern si c'est dans un .h privé)
    "Un homme sage ne croit que la moitié de ce qu’il lit. Plus sage encore, il sait laquelle".

    Consultant indépendant.
    Architecture systèmes complexes. Programmation grosses applications critiques. Ergonomie.
    C, Fortran, XWindow/Motif, Java

    Je ne réponds pas aux MP techniques

  16. #16
    Expert éminent
    Avatar de Melem
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2006
    Messages
    3 656
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Janvier 2006
    Messages : 3 656
    Points : 8 389
    Points
    8 389
    Par défaut
    Je suis plutôt d'accord avec souviron34 pour cette remarque :
    on arrive de but en blanc sur 2 fichiers.. Pédagogiquement, il serait bon de commencer par un, puis d'expliquer que l'intéressant est de pouvoir séparer les fonctions dans un fichier séparé (avec les diverses raisons : modification, exportation, clarté..). Ce qui donnerait le pourquoi on veut un .h (voir plus bas)
    Présentée de cette façon là, on peut en effet éviter de déclarer des fonctions dans un .c tout en gardant une bonne pédagogie. Merci de ton tuyau.

    Je le suis nettement moins avec les autres :

    Citation Envoyé par souviron34
    Tu donnes la compilation sous CodeBlock. Une compilation sous unixoide (ou cygwin) serait également pédagogiquement un bon exemple, puisqu'on voit chaque étape de la compilation séparément.
    On ne voit pas chaque étape de la compilation dans l'EDI ? Peux-tu expliquer ce que l'on ne voit pas ?

    Citation Envoyé par souviron34
    le mot-clé extern :
    Nous avons déjà résolu le problème pour les fonctions, ne reste donc plus que les variables
    Késako ? D'où ça vient ? On a rien résolu du tout à ce stade, et il n'y a pas d'explication (d'autant plus que tu ne te sers pas d'extern...)
    On a résolu le problème d'utilisation d'une fonction externe : il suffit de la déclarer. On n'avait pas besoin d'extern pour ça, comme il est clairement expliqué dans le tutoriel. Et à la ligne que tu cites on s'apprête à voir comment utiliser une variable externe. Là il faut maintenant extern. Mais ce n'est peut-être pas assez clair, donc je vais essayer de trouver une meilleure tournure.

    Citation Envoyé par souviron34
    les structures opaques : pourquoi prendre comme exemple ça, qui est compliqué et inutile ? Pourquoi ne pas se servir simplement de FILE, ou de struct tm, et pourquoi parler directement de créateur/destructeur ??? quand on utilise FILE, on n'a ni créateur ni destructeur en tant que tel... Notions inutiles et superflues dans le cadre des types opaques (en outre, Emmanuel Delahaye a fait un excellent chapitre dessus, si tu veux expliquer vraiment réfère-toi à cette partie de son cours).
    - Contrairement à ce que tu dis, je ne connais pas d'exemple plus simple de structure opaque. Certes inutile dans la vie pratique, mais le but était de présenter le plus simplement possible le concept, pas de proposer une bibliothèque professionnelle.
    - FILE est une structure bien plus compliquée que celle que j'ai proposée, et son implémentation est inconnue, ou du moins dépendante du système.
    - struct tm n'est pas une structure opaque ...
    - Et pourquoi parler directement de créateur/destructeur ? Parce qu'une structure opaque en a obligatoirement besoin. Par exemple pour la structure FILE : constructeur = fopen, destructeur = fclose.
    - Je ne sais pas si on aura l'honneur et le plaisir d'avoir Emmanuel dans ce fl, mais j'ose espérer qu'il sera plutôt du même avis que moi sur ce coup là.

    Citation Envoyé par souviron34
    le mot-clé static : erreur, puisque tu déclares le protype en static mais pas la fonction...
    La norme ne requiert pas que la définition commence aussi avec le mot-clé static. static est juste requis dans la déclaration :
    Citation Envoyé par 6.2.2 Linkages of identifiers
    If the declaration of a file scope identifier for an object or a function contains the storageclass specifier static, the identifier has internal linkage.
    Tu as du mélanger avec inline ou autre chose .

    Citation Envoyé par souviron34
    Une bibliothèque statique (.lib ou .a) est un fichier qui regroupe un ou plusieurs modules objets. Elles s'utilisent donc de la même manière que ces derniers.
    C'est également vrai des bibliothèques dynamiques, et NON elles ne s'utilisent pas de la même manière (il faut les mot-clés spéciaux à l'édition de lien)
    Ton attitude est celle d'une personne qui cherche juste à critiquer mais pas à comprendre, et moins encore à construire. Ce n'est pas non plus comme si j'ai laissé le tutoriel s'achever sur cette phrase. Il y a une suite qu'il faut lire ...

    Même remarque pour l'histoire de bibliothèque dynamique.

    Citation Envoyé par souviron34
    le concept d'API :

    outre le fait que ce chapitre est franchement plus que faible (avec un tel titre) quel est son intérêt dans le cadre des fichiers d'entête si ce n'est simplement d'égaler API avec définition dans le .h ?
    Là aussi je suis d'accord. En fait, je voulais à la base fournir une petite initiation à l'utilisation de l'API Windows en guise d'application pratique supplémentaire de ce que l'on vient d'apprendre, mais j'ai mis du temps à trouver un bon thème et à la longue j'ai abandonné l'idée sans supprimer cette pauv' section. Je me suis dit que ça fera toujours un peu de terminologie . Maintenant qu'on en reparle, l'API MCI Audio serait peut-être un bon thème ? Une deuxième démo avec cette fois-ci une bibliothèque open source aussi serait peut-être aussi la bienvenue. Je pense en ce moment à PDCurses. Qu'en dis-tu ?

    Citation Envoyé par D[r]eadLock
    Je suis plutôt d'accord avec Sékiltoyai. En effet, si tu change le prototype d'une fonction, il faut la changer dans le .c de celui qui appelle la fonction. Ça ne devient "plus" modulaire.
    Ici, le but n'était pas encore de parler de modularité ni de réutilisabilité du code. Je voulais juste montrer qu'il était possible de répartir l'implémentation d'un projet sur plusieurs fichiers sources. C'est après seulement qu'il est intéressant de se poser le problème de modularité. Voilà comment moi je décompose un problème complexe en sous-problèmes simples selon les principes exposés par Descartes dans son fameux Discours sur la méthode. Avec la décomposition proposée par souviron34, ça va encore aller mieux.

    Citation Envoyé par D[r]eadLock
    Et pire, le compilo peut ne rien voir et générer du code faux (genre somme prend des pointeurs ou une signature différente).
    Et c'est quoi la différence ici si on utilisait un fichier d'en-tête ?

    Merci pour toutes vos critiques et n'hésitez surtout pas s'il y en a d'autres.

    Melem

  17. #17
    Membre éclairé
    Avatar de D[r]eadLock
    Profil pro
    Inscrit en
    Mai 2002
    Messages
    504
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France

    Informations forums :
    Inscription : Mai 2002
    Messages : 504
    Points : 750
    Points
    750
    Par défaut
    Citation Envoyé par Melem Voir le message
    Et c'est quoi la différence ici si on utilisait un fichier d'en-tête ?
    C'est que tu es obligé (si tu compiles avec -Werror, ou du moins supprime les warnings les plus dangereux) d'avoir un code correct:
    • Si tu oublies de modifier le .h: tu as une erreur à la compil du source qui implémente la fonction error: conflicting types for 'somme'
    • Si tu oublies de modifier le "client" (le main), tu as un warning/erreur: genre argument 1 makes pointer from integer without a cast

    En gros le compilo t'aide à changer tes prototypes sans faire de grosses boulettes.

    Le seul 'danger' (i.e. de faire confiance au compilo en cas de changement d'API) est d'oublier d'inclure le .h dans le .c qui implémente la fonction (c'est pour ça que gcc propose -Wmissing-prototypes pour "forcer" la définition à être quelque part (pour moi, dans un .h ), à noter que ce warning ne s'applique pas aux fonctions 'static')).

    Si je relève ce point (mettre le extern... dans un .h) c'est que je suis déjà tombé sur des cas comme ça au boulot et qui auraient pu être évité par des bonnes pratiques. Du coup, je trouve 'dangereux' de "dire" que l'on peut mettre des 'extern...' dans du code "client" qui pour moi relève plus du hack de la programmation "propre"

  18. #18
    Expert éminent
    Avatar de Melem
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2006
    Messages
    3 656
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Janvier 2006
    Messages : 3 656
    Points : 8 389
    Points
    8 389
    Par défaut
    Citation Envoyé par D[r]eadLock
    En gros le compilo t'aide à changer tes prototypes sans faire de grosses boulettes.
    Je vois.

    Citation Envoyé par D[r]eadLock
    Du coup, je trouve 'dangereux' de "dire" que l'on peut mettre des 'extern...' dans du code "client" qui pour moi relève plus du hack de la programmation "propre"
    Ce que moi j'en pense, c'est que le C en tout cas le permet et que je ne vois donc toujours pas d'inconvénient à l'utiliser dans un but pédagogique. Ce qu'il manque réellement, c'est un avertissement sur ses éventuels dangers. En plus, ça fera une bonne introduction aux fichiers d'en-tête. Mais j'avoue que le plan proposé par souviron34 aussi est tout aussi intéressant. Personnellement, lequel trouves-tu meilleur ?

  19. #19
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 15
    Points : 17
    Points
    17
    Par défaut
    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
     
    #include <stdio.h>
     
    - static int id(int x); /* ... */
    - int id(int x)
    + static int   id(int x)
    {
        return x;
    }
     
    - int main()
    + int          main(void)
    {
        int      x = 0;
     
        printf("id(%d) = %d\n", x, id(x));
     
        return 0;
    }
    remise des fonctions dans l'ordre,
    l'ordre ne compte pas. (analogie avec l'arrangement). (mon humour est particulier... )


    apres juste pour la forme, une fonction produit qui marche, avec les elements qu'elle accepte selon son prototype, pourrait avoir du sens.
    (depassement de la valeur d'un int en retour (ce qui est acceptable... tout comme pour l'addition), impossibilite d'avoir b negatif fonctionnel). mais c'est juste pour la forme.

  20. #20
    gl
    gl est déconnecté
    Rédacteur

    Homme Profil pro
    Inscrit en
    Juin 2002
    Messages
    2 165
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2002
    Messages : 2 165
    Points : 4 637
    Points
    4 637
    Par défaut
    Citation Envoyé par souviron34 Voir le message
    les fichiers d'entête : outre le fait que cela arrive comme un cheveu sur la soupe (voir plus haut), là encore tu ne déclares pas les prototypes comme extern.. Mauvaise pratique...
    Sur un prototype, extern n'est pas indispensable (l'absence de "storage class specifier" est équivalent à l'utilisation de extern).

    Dans le cas d'une déclaration à l'intérieur d'un fichier source, la présence d'extern peut éventuellement avoir un rôle documentaire intéressant.
    Dans un header, à part pour avoir une symétrie entre la déclaration de fonction et la déclaration de variable, il n'y a pas vraiment d'intérêt. En tout cas rien qui puisse faire considérer l'absence d'extern comme une mauvaise pratique dans l'absolue [1].


    Citation Envoyé par Melem Voir le message
    La norme ne requiert pas que la définition commence aussi avec le mot-clé static. static est juste requis dans la déclaration
    Juste un petit aparté, or cas particulier d'appel croisé, je n'ai jamais vu réellement d'intérêt à avoir à la fois une simple déclaration et une définition d'une fonction static.
    Je préfère amplement n'avoir qu'une définition et ordonner mes fonctions correctement.


    [1] Si la norme de codage l'impose, je conçois que ne pas le mettre et donc ne pas respecter les conventions stylistiques de ladite norme soit une mauvaise pratique. Mais là ce qui pêche n'est pas l'absence de extern en soi mais le non respect de la norme.

Discussions similaires

  1. Compilation séparée ?
    Par kromartien dans le forum C
    Réponses: 8
    Dernier message: 22/04/2007, 10h41
  2. Compilation séparée avec devc++
    Par javamax dans le forum Dev-C++
    Réponses: 6
    Dernier message: 08/02/2007, 18h56
  3. Compilation séparée
    Par oliv928 dans le forum Dev-C++
    Réponses: 6
    Dernier message: 02/01/2007, 17h41
  4. Compilation séparée sous devcpp
    Par Mic75 dans le forum Dev-C++
    Réponses: 1
    Dernier message: 23/08/2006, 15h33
  5. Compilation séparée avec dev C/C++
    Par benjiprog dans le forum Dev-C++
    Réponses: 5
    Dernier message: 07/11/2005, 18h26

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