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 :

J'ai rien compris au .h


Sujet :

C

  1. #1
    Futur Membre du Club Avatar de L0ser
    Homme Profil pro
    Etudiant
    Inscrit en
    Août 2017
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Etudiant

    Informations forums :
    Inscription : Août 2017
    Messages : 8
    Points : 9
    Points
    9
    Par défaut J'ai rien compris au .h
    Salut a tous je suis nouveau sur le forum et débutant en C.



    Je suis actuellement les cours de C et je n'ai rien compris a la programmation modulaire en C.

    Plus particulièrement la partie des .h et des .c dans l’ensemble j'ai compris leurs rôles mais je ne sais pas comment les mètrent en pratique.

    Pour faire simple je sais ce que c'est et à quoi ça sert mais je ne sais pas comment écrire un .h et un .c pour mon fichier main.c.

    Merci d'avance.

  2. #2
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 690
    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 690
    Points : 30 985
    Points
    30 985
    Billets dans le blog
    1
    Par défaut
    Bonjour

    Pour faire simple: un ".h" est juste une liste d'éléments nécessaires à l'utilisation d'une fonction que tu veux publier (ou d'une fonction publiée par un autre que tu veux utiliser).

    Imaginons par exemple que j'écrive une fonction "calculSurfaceCercle" destinée à calculer la surface d'un cercle de rayon "r". Je vais écrire donc ma fonction ainsi
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    #define PI     (3.1415926)
    double calculSurfaceCercle(double rayon) {
        return PI * rayon * rayon;
    }

    Maintenant je publie ma fonction sur le net mais comme je tiens à mes droits d'auteurs, je ne publie que la version exécutable et non le code source. Toi, cette fonction t'intéresse parce que tu n'as pas envie de la réécrire alors tu la récupères pour l'inclure dans ton programme. Se pose alors 2 soucis
    1) comment cette fonction doit-être utilisée (que veut-elle ? que renvoie-t-elle ?)
    2) c'est quoi ce "PI" qu'elle utilise ?

    Pour que tu puisses utiliser ma fonction que tu m'as acheté super cher, je suis obligé de te fournir la réponse à ces deux questions. Ben la réponse, c'est le ".h".

    J'écris alors
    Code calculSurfaceCercle.h : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    #define PI     (3.1415926)
    double calculSurfaceCercle(double);

    En lui-même ce fichier ne livre aucun secret. Tout ce qu'il dit est simpement que je définis une macro nommée "PI" et une fonction qui reçoit un double et retourne un double. Mais le coeur de cette fonction (comment elle travaille, quel algorithme secret et superpuissant j'utilise) reste stocké dans le module compilé que tu peux utiliser mais que tu ne peux pas lire (parce qu'écrit en langage machine donc incompréhensible pour un humain).

    Toi, tu récupères donc ce ".h" que tu inclueras à chaque fois que tu voudras utiliser ma fonction.

    Se pose alors un petit ennui: tu n'es pas le seul à utiliser ma fonction. Peut-être que mon pote Paul a créé une fonction "calculVolumeSphere" et que cette fonction utilise la mienne. Paul inclus donc lui-aussi mon ".h" dans son propre ".h".
    Exemple de ".h" de Paul
    Code calculVolumeSphere.h : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    #include <calculSurfaceCercle.h>
    double calculVolumeSphere(double);

    Maintenant toi tu veux utiliser la fonction de Paul et aussi la mienne. Mais sans te prendre la tête. Tu écriras donc
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    #include <calculSurfaceCercle.h>
    #include <calculVolumeSphere.h>
    ...
    Et là petit souci: en incluant le ".h" de Paul tu as déjà automatiquement inclu mon ".h" mais ça tu ne le sais pas (comme je l'ai dit tu ne veux pas te prendre la tête en décortiquant tous les ".h" pour voir les conflits possibles, tu veux juste que ça marche). Mais ensuite en incluant à la ligne en dessous mon ".h" tu l'inclus alors une seconde fois. Et là, ton compilo va gueuler (parce que déjà il verra que la fonction" calculSurfaceCercle" est déclarée deux fois).

    Pour éviter ce soucis, c'est à moi de prévoir le coup. Et ça se fait très simplement avec la compilation conditionnelle
    Code calculSurfaceCercle.h : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    #ifndef _CALCUL_SURFACE_CERCLE_H_
    #define _CALCUL_SURFACE_CERCLE_H_
    #define PI     (3.1415926)
    double calculSurfaceCercle(double);
    #endif // _CALCUL_SURFACE_CERCLE_H_

    Maintenant, en incluant le ".h" de Paul, il va inclure mon ".h". A ce moment là, la macro "_SURFACE_CERCLE_H_" n'existant pas, elle sera définie et ça incluera aussi le reste. Puis, lors de ton include de mon ".h", la macro "_SURFACE_CERCLE_H_" étant déjà définie, tout ce qui est entre le "#ifdef" et le "#endif" sera purement ignoré.
    Et si demain tu n'as plus envie/besoin de la fonction de Paul, te suffit d'enlever son ".h" de ton programme sans que cela nuise à l'utilisation de ma fonction "calculSurfaceCercle".
    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
    Expert éminent
    Avatar de Pyramidev
    Homme Profil pro
    Développeur
    Inscrit en
    Avril 2016
    Messages
    1 471
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur

    Informations forums :
    Inscription : Avril 2016
    Messages : 1 471
    Points : 6 110
    Points
    6 110
    Par défaut
    Bonjour,

    Citation Envoyé par L0ser Voir le message
    Plus particulièrement la partie des .h et des .c dans l’ensemble j'ai compris leurs rôles mais je ne sais pas comment les mètrent en pratique..
    Je ne sais pas quelle partie tu as comprise et laquelle tu n'as pas comprise alors, dans le doute, je vais rappeler le principe, en complément au message de Sve@r.

    Lors de la compilation au sens large, dans un premiers temps, chaque fichier ".c" est compilé, indépendamment des autres fichiers ".c", pour former un fichier objet, par exemple un fichier ".o" (l'extension dépend du compilateur). Dans un deuxième temps, lors de l'édition des liens, les fichiers objets sont rassemblés pour former un exécutable.

    Il arrive souvent qu'un fichier ".c" utilise une fonction définie ailleurs. Par exemple, admettons que l'on ait les fichiers suivants :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    // Contenu de calcul.c
     
    int somme(int a, int b)
    {
        return a + b;
    }
     
    int produit(int a, int b)
    {
        return a * b;
    }
    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
    // Contenu de main.c
     
    #include <stdio.h>
     
    int somme(int a, int b);
    int produit(int a, int b);
     
    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;
    }
    Pour que "main.c" ait le droit d'utiliser somme et produit définis dans le fichier objet "calcul.o" (qui sera le résultat de la compilation de "calcul.c"), il est obligé de déclarer en amont les fonctions qu'il utilise :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    int somme(int a, int b);
    int produit(int a, int b);
    Or, quand tu as plein de fonctions qui sont utilisées dans plein de fichiers ".c", maintenir des listes interminables de déclaration de fonctions, de structures, etc. au début de chaque fichier ".c" représente une grosse perte de temps.

    La solution est d'écrire un fichier ".h" qui ressemble à ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    // contenu de "calcul.h"
     
    #ifndef INCLUDE_SOMME_H
    #define INCLUDE_SOMME_H
     
    int somme(int a, int b);
    int produit(int a, int b);
     
    #endif
    Et, dans les fichiers qui utilisent ces fonctions, à la place d'écrire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    int somme(int a, int b);
    int produit(int a, int b);
    on écrit :
    La compilation au sens large d'un fichier ".c" commence par l'exécution du préprocesseur. #include "calcul.h", c'est une directive qui dit au préprocesseur de copier-coller à cet endroit tout le contenu de "calcul.h".

    Dans les fichiers ".h", les 3 lignes de code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    #ifndef MACRO_AVEC_UN_NOM_UNIQUE
    #define MACRO_AVEC_UN_NOM_UNIQUE
     
    ...
     
    #endif
    assurent que le contenu ne soit copié-collé qu'au plus une fois par le préprocesseur pour chaque fichier ".c" qui inclut ce fichier, directement ou indirectement.
    Une inclusion peut arriver indirectement quand on inclut un ".h" qui inclut lui même un autre ".h", mais Sve@r l'a déjà expliqué.

    Citation Envoyé par Sve@r Voir le message
    Et là, ton compilo va gueuler (parce que déjà il verra que la fonction" calculSurfaceCercle" est déclarée deux fois).
    Dans ton exemple, GCC n'affichera un avertissement pour calculSurfaceCercle que si on utilise l'option de compilation -Wredundant-decls qui ne fait malheureusement pas partie de -Wall -Wextra. Pour la macro PI, il ne râlera pas non plus car on a le droit de définir une macro déjà définie, à condition que la nouvelle définition soit identique à l'ancienne.

    Par contre, si on met la définition de la fonction directement dans le ".h" :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    inline static double calculSurfaceCercle(double rayon) {
        return PI * rayon * rayon;
    }
    là, effectivement, si on se retrouve avec cette définition en double, le compilateur signalera une erreur.

  4. #4
    Futur Membre du Club Avatar de L0ser
    Homme Profil pro
    Etudiant
    Inscrit en
    Août 2017
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Etudiant

    Informations forums :
    Inscription : Août 2017
    Messages : 8
    Points : 9
    Points
    9
    Par défaut Merci
    Un grand MERCI a vous deux j'ai enfin compris le .h


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

Discussions similaires

  1. [XSLT] XML débutant : Rien compris !
    Par popy67 dans le forum XSL/XSLT/XPATH
    Réponses: 7
    Dernier message: 23/05/2008, 16h41
  2. Rien compris, OpenGL et Z axis !?!
    Par _ZoD_ dans le forum OpenGL
    Réponses: 7
    Dernier message: 02/10/2007, 15h40
  3. congés payés rien compris
    Par ti'lou dans le forum Congés
    Réponses: 13
    Dernier message: 28/02/2007, 19h06
  4. [Noob] Mon premier programme : rien compris
    Par uNd3r² dans le forum Dev-C++
    Réponses: 5
    Dernier message: 19/12/2006, 21h23

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