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 :

Decouper et classer un source


Sujet :

C

  1. #1
    Membre éclairé
    Profil pro
    Inscrit en
    Avril 2005
    Messages
    309
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2005
    Messages : 309
    Par défaut Decouper et classer un source
    Bonjour à tous.

    Mon code marche nickel, sans warning, sans error.

    Mais, pour y voir plus clair, j'ai essayé de sortir une des fonctions dans un autre fichier "Classes.c"
    void ClassRegister(HINSTANCE hInstance, int nCmdShow)
    {
    WNDCLASS wc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wc.hInstance = hInstance;
    wc.lpfnWndProc = WndProc;
    wc.lpszClassName = "Classe 1";
    wc.lpszMenuName = NULL;
    wc.style = CS_HREDRAW | CS_VREDRAW;

    RegisterClass(&wc);

    }
    J'ai donc créé ce fichier, l'ai nommé avec l'extension "Classes.c" et ajouté au projet

    A la place ou etait cette fonction, j'ai ajouté la ligne
    Et maintenant, j'ai beau faire ce que je veux pas moyen de compiler

    --------------------Configuration: FenetreVC - Win32 Debug--------------------
    Compiling...
    Classes.c
    C:\Documents and Settings\Pc\Bureau\Nouveau dossier\PbEnC v1.0 du 101031\Donnees\FenetreVC\Classes.c(1) : error C2146: syntax error : missing ')' before identifier 'hInstance'
    C:\Documents and Settings\Pc\Bureau\Nouveau dossier\PbEnC v1.0 du 101031\Donnees\FenetreVC\Classes.c(1) : error C2061: syntax error : identifier 'hInstance'
    C:\Documents and Settings\Pc\Bureau\Nouveau dossier\PbEnC v1.0 du 101031\Donnees\FenetreVC\Classes.c(1) : error C2059: syntax error : ';'
    C:\Documents and Settings\Pc\Bureau\Nouveau dossier\PbEnC v1.0 du 101031\Donnees\FenetreVC\Classes.c(1) : error C2059: syntax error : ','
    C:\Documents and Settings\Pc\Bureau\Nouveau dossier\PbEnC v1.0 du 101031\Donnees\FenetreVC\Classes.c(1) : error C2059: syntax error : ')'
    Error executing cl.exe.

    Classes.obj - 5 error(s), 0 warning(s)
    So quelqu'un voit ce que j'aurais pas du faire
    Merci

  2. #2
    Invité
    Invité(e)
    Par défaut
    Bonjour,

    Le nouveau fichier est maintenant compilé indépendamment du premier fichier.
    Je pense qu'il faut l'exclure de la liste des objets à compiler.

  3. #3
    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
    C'est une mauvaise idée de faire des include de fichier .c. Il faut procéder par compilation séparée.

    Voir par exemple le tuto de Melem : La compilation séparée

  4. #4
    Membre éclairé
    Profil pro
    Inscrit en
    Avril 2005
    Messages
    309
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2005
    Messages : 309
    Par défaut
    Bonjour à tous les deux et merci de vos réponses

    Je croyais bêtement que c'était tout bete et que l'on pouvait "Scinder" le code en autant de partie que l'on veut du moment que l'on mette les includes dans le bon ordre

    Apparemment cela ne marche pas comme ça en C

    Je pense qu'il faut l'exclure de la liste des objets à compiler.
    Je vais essayer de trouver cette liste

    C'est une mauvaise idée de faire des include de fichier .c.
    Alors ça des mauvaises idées...apparemment j'en ai un stock pour le C

    Pourquoi en ".c" si je veux scinder mon code source, cela aurait marché si je change l'extension ???

  5. #5
    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
    Pourquoi en ".c" si je veux scinder mon code source, cela aurait marché si je change l'extension ???
    Non, l'extension n'a rien à voir.
    Par là, je voulais dire ce qu'on trouve habituellement dans un .c : un fichier contenant des fonctions, des déclarations de variables,...
    On inclue généralement des fichiers contenant des définitions de type, des prototypes de fonctions,... (et ils ont traditionnellement une extension en .h), enfin ce qu'on veut pouvoir partager avec plusieurs unités de compilation séparées.

  6. #6
    Membre éclairé
    Profil pro
    Inscrit en
    Avril 2005
    Messages
    309
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2005
    Messages : 309
    Par défaut
    D'accord..moi je voulais decouper mon code afin qu'il soit plus organisé....
    Car quand le code est long on doit pouvoir classer les fonctions par style ou autre, non ???
    Cela n'est pas prévu par le C, de pouvoir mettre des fichier INCLUDES qui sont exactement comme un ".c"

    En attendant, comme j'avais cru que tu me parlais de l'extension, j'ai tenté de changer justement cette extension.
    Quand j'ai voulu sauvegarder ma fonction, je me suis aperçu que VC me proposait plusieurs formats pour les includes ".h .hpp .hxx .inl et .tlh

    Alors je sais que les .h c'est pour les header, j'ai supposé que .hpp et .hxx aussi .tlh je savais pas...et .inl je trouvais que ça ressemblait drôlement a INCLUDE, alors j'ai essayé....et tu vas pas y croire..j'ai inclus et compilé le .inl puis tout rebuildé...et plus d'erreur

    Alors ou j'ai tout juste, ou alors j'ai encore fait une bêtise tellement grosse que même les programmeurs de CROSOFT auraient pas prévu qu'on puisse la faire et ont laissé passé ça
    Ai-je bien fait, d'utiliser ce genre d'extension, ou je me suis encore lamentablement vautré

  7. #7
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Chercheur d'emploi
    Inscrit en
    Septembre 2007
    Messages
    7 487
    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 487
    Par défaut
    Citation Envoyé par andrebernard Voir le message
    D'accord..moi je voulais decouper mon code afin qu'il soit plus organisé....
    Car quand le code est long on doit pouvoir classer les fonctions par style ou autre, non ???
    Cela n'est pas prévu par le C, de pouvoir mettre des fichier INCLUDES qui sont exactement comme un ".c"
    Ce n'est pas ce qu'il a dit.

    « #include » permet d'insérer effectivement n'importe quoi à l'endroit où la directive est rédigée. Le compilateur enchaînera les fichiers linéairement. On peut même, dans l'absolu, commencer l'appel à une fonction dans un fichier et la terminer dans l'autre. Évidemment, faire cela serait très sale.

    Par contre, décomposer le contenu d'un seul fichier en plusieurs pour le réintégrer après dans le même fichier, ça n'a aucun intérêt. Ni pour le compilateur, qui est obligé de tous les relire un par un dans l'ordre et de tout reconstruire depuis zéro (donc autant tout laisser dans le même fichier), ni pour toi, qui non seulement doit ouvrir plusieurs fichiers pour maintenir ton code, mais qui ne peut pas savoir a priori si un fichier *.c dans ton répertoire de dépôt peut être compilé seul ou si c'est en fait un extrait d'un fichier plus grand.

    C'est justement cette dernière notion qui est importante : l'usage veut qu'un fichier *.c contienne du code, ou au moins des définitions (de variables ou autres) et que ce matériel soit compilable en un fichier objet. Autrement dit : on doit pouvoir faire correspondre un fichier *.o à chaque fichier *.c. L'idée sous-jacente est que, même si ce fichier objet *.o n'est pas directement exécutable, on puisse directement utiliser ce qu'il contient sans avoir à recompiler le fichier source.

    D'une part c'est exactement le principe de la bibliothèque statique (sous UNIX, les bibliothèques statiques sont des fichiers *.a, eux-mêmes étant les fichiers « archives » historiques d'UNIX créés avec la commande « ar », et ces fichiers ne contiennent en fait que des fichiers objets compilés *.o.

    Ensuite, l'intérêt même de la compilation séparée est de ne pas avoir à tout re-compiler depuis le début à chaque modification mineure. En principe, donc, à chaque fois que tu modifies un *.c, tu recompiles seulement celui-ci et tu ne régénères que le *.o qui lui correspond. Tu demandes ensuite au linker d'associer tous les *.o entre eux pour former l'exécutable final, ce qu'il fera en liant ton *.o tout neuf et tous les autres que tu avais compilé avant.

    Ce principe deviendra même nécessaire lorsque tu commenceras à écrire tes propres Makefiles et que tu devras gérer les dépendances entre les différents composants de ton projet.

    Si tu veux organiser le contenu d'un long fichier *.c, soit tu construis ton projet selon le principe ci-dessous (rien ne t'interdit de créer des fichiers objets minuscules), soit tu choisis un éditeur qui te propose des facilités pour le faire. Je ne connais pas Pelles C mais, à en voir les captures d'écran, cet IDE propose, tout comme Visual Studios, un navigateur de classes et/ou de fonctions sur le côté, mis à jour en temps réel et qui te permet de sauter directement vers l'entité choisie en cliquant sur son nom. Et même sans IDE, bon nombre d'éditeurs de textes tels VIM sous Unix permettent de faire des « replis », qui consistent à masquer volontairement toute une portion de ton fichier et la remplacer par une seule ligne, qui se développe quand tu cliques dessus (ou entre la commande appropriée), pour laisser réapparaître tout ce qu'elle contient.

  8. #8
    Membre éclairé
    Profil pro
    Inscrit en
    Avril 2005
    Messages
    309
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2005
    Messages : 309
    Par défaut
    Voui voui OBSIDIAN

    Je l'entend bien comme ça, enfin j'espère, car c'est pas toujours facile de se comprendre par écrit

    Je voulais faire un .c par type de fonctions
    Un pour gérer les dossiers/fichiers
    Un pour gérer le graphisme
    Un pour mes modules de cryptage
    Un pour la gestion du texte
    Etc...

    Comme ceci, quand je cherche une fonction, je sais ou elle est en quelques secondes.

    Je pense particulièrement a la création de DLL, je n'en suis pas encore la, mais c'est un de mes objectifs premiers en C.
    J'ai fait exactement la même organisation dans le langage d'où je viens, et aussi dans VB
    Pour les DLL VB, c'est chocolat car il ne sait faire que de l'activeX inintéressant à mon gout, mais pour mon langage actuel il sait créer des DLL standard C (StdCall, et Cdel)

    J'ai donc créé 800 fonctions en DLL dans lesquels je pioche avec mes programmes VB ou autre

    Si je n'avais pas fait cette organisation, j'aurais abandonné depuis longtemps, c'est la raison pour laquelle, je voulais m'assurer de pouvoir faire la meme chose avec le C.
    C'est un peu plus compliqué car il faut gérer le header apparemment et la non duplication des déclaration par une directive préprocesseur, mais je crois avoir compris aujourd'hui que c'est possible, et même ce qu'il faut faire lorsque l'on gère moultes centaines de fonctions

    Ou alors c'est que j'ai encore rien compris pour ce qui est de ce sujet en C

    Dis moi que j'ai compris....dis le moi !!!! que je n'ai pas la sensation d'avoir perdu ma journée

  9. #9
    Membre éclairé
    Profil pro
    Inscrit en
    Avril 2005
    Messages
    309
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2005
    Messages : 309
    Par défaut
    Je viens de faire des essais, j'ai lu le TUTO de MELEM et fait comme il a dit.
    Mais il reste quand même un probleme de compilation.
    Apparemment un doublon de déclaration
    Deleting intermediate files and output files for project 'FenetreVC - Win32 Debug'.
    --------------------Configuration: FenetreVC - Win32 Debug--------------------
    Compiling...
    Classes.c
    Fenetre.c
    Main.c
    Linking...
    Fenetre.obj : error LNK2005: _ClassRegister already defined in Classes.obj
    Debug/FenetreVC.exe : fatal error LNK1169: one or more multiply defined symbols found
    Error executing link.exe.
    Creating browse info file...

    FenetreVC.exe - 2 error(s), 0 warning(s)
    Y'a un truc que j'ai vraiment pas compris.
    Y'a encore du flou dans les INCLUDES pour moi, car quand j'en met pas il me les demandes, et quand je les mets dans tous les fichiers, il dit que y'en a trop

    Bon apparemment chaque fichier .c est compilé un a un, pour creer des .obj
    Ces obj sont linké pour créer l'EXE par le LINKER
    J'espere avoir tout compris, car depuis deux jours que je me bourre le cerveau et vu l'heure....des fois j'me demande

    Mais par quel fichier le linker commence, dans quel ordre ??
    Et pourquoi j'ai quand meme un doublon de declaration, alors que j'ai mis la protection de MELEM dans chaque .h

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    #ifndef H_Fenetre
     #define H_Fenetre
     #endif
    Classes.c
    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
    #include <windows.h>
    #include "Classes.h"
    #include "Fenetre.h"
     
    void ClassRegister(HINSTANCE hInstance, int nCmdShow)
    {
    	WNDCLASS wc;
    	wc.cbClsExtra     = 0;
    	wc.cbWndExtra     = 0;
    	wc.hbrBackground  = (HBRUSH)(COLOR_WINDOW + 1);
    	wc.hCursor        = LoadCursor(NULL, IDC_ARROW);
    	wc.hIcon          = LoadIcon(NULL, IDI_APPLICATION);
    	wc.hInstance      = hInstance;
    	wc.lpfnWndProc    = WndProc;
    	wc.lpszClassName  = "Classe 1";
    	wc.lpszMenuName   = NULL;
    	wc.style          = CS_HREDRAW | CS_VREDRAW;
     
    	RegisterClass(&wc);
     
    }
    Fenetre.c
    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
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    #include <windows.h>
    #include "Fenetre.h"
     
    LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
        static HINSTANCE hInstance;
     
        switch (message)
        {
        case WM_CREATE:
     
            hInstance = ((LPCREATESTRUCT)lParam)->hInstance;
            CreateWindow("BUTTON", "OK", WS_CHILD | WS_VISIBLE, 0, 0, 100,24, hwnd, (HMENU)1, hInstance, NULL);
     
            break;
     
        case WM_COMMAND:
            /***************************************************\
            * LOWORD(wParam) = ID du contrôle ou du menu        *
            * HIWORD(wParam) = Raison du message (notification) *
            \***************************************************/
     
            switch(LOWORD(wParam))
            {
     
            case 1:
     
                switch(HIWORD(wParam))
                {
     
                case BN_CLICKED:
                    Beep(1000, 100);
                    break;
     
                default:
                    break;
                }
     
                break;
     
            case 2:
     
                switch(HIWORD(wParam))
                {
     
                case BN_CLICKED:
     
                    Beep(100, 100);
                    break;
     
                default:
     
                    break;
     
                }
     
                break; 
     
            default:
     
                break;
     
            }
     
            break; /* case WM_COMMAND */
     
        case WM_DESTROY:
     
            PostQuitMessage(0);
            break;
     
        default:
     
            return DefWindowProc(hwnd, message, wParam, lParam);
     
        }
     
        return 0;
     
    }
     
    int OuvertureFenetre(HINSTANCE hInstance, int nCmdShow)
    {
     
     HWND hWnd;
     MSG msg;
     HWND hWndB1;
     HWND hWndB2;
     
     hWnd = CreateWindow("Classe 1", "Notre première fenêtre", WS_OVERLAPPEDWINDOW,100, 100, 600, 300, NULL,NULL,hInstance,NULL);
     hWndB1 = CreateWindow("BUTTON", "OK1", WS_CHILD | WS_VISIBLE, 100,100, 100,24, hWnd, (HMENU)1, hInstance, NULL);
     hWndB2 = CreateWindow("BUTTON", "OK2", WS_CHILD | WS_VISIBLE, 200,200, 100,24, hWnd, (HMENU)2, hInstance, NULL);
     ShowWindow(hWnd, nCmdShow);
     
    	while (GetMessage(&msg, NULL, 0, 0))
     {	 
    	 TranslateMessage(&msg);
    	 DispatchMessage(&msg);
    	}
     
     return (int)msg.wParam;
     
    }
     
    #include "Classes.c"
    }
    Main.c
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    #include <windows.h>
    #include "Classes.h"
    #include "Fenetre.h"
     
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
    {
     
     // Create first class
     ClassRegister(hInstance, nCmdShow);
     
      // Create the windows
    	return OuvertureFenetre(hInstance, nCmdShow);
     
    }
    Classes.h
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    #ifndef H_Classes
     
     #define H_Classes
     void ClassRegister(HINSTANCE hInstance, int nCmdShow); 
     
    #endif
    Fenetre.h
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    #ifndef H_Fenetre
     
     #define H_Fenetre
     int OuvertureFenetre();
     LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); 
     
    #endif

  10. #10
    Invité
    Invité(e)
    Par défaut
    Dans Fenetre.C il faut retirer l'include de Class.C.

  11. #11
    Membre éclairé
    Profil pro
    Inscrit en
    Avril 2005
    Messages
    309
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2005
    Messages : 309
    Par défaut
    Merci beaucoup NUDGER

    T'es trop fort..en plus a minuit...

    Alors la..j'avoue que j'y comprend rien...mais je vais plancher sur le probleme, car il faut que je comprenne

    Si on pouvait voir comment le linker s'y prend et dans quel ordre, pour linker les OBJ, peut etre que j'aurais compris ou il passe deux fois

    Le coup des includes...c'est encore pas simple a comprendre
    Surtout quand on y met les .h
    Et pourtant j'ai bien lu le TUTO

    Encore merci et bonne journée

  12. #12
    Invité
    Invité(e)
    Par défaut
    Bonjour,
    Je crois que vous avez tout à fait raison de vouloir comprendre.
    Les include incluent des fichiers d'entête (.h). C'est exactement comme si le code du fichier d'entête était écrit à cet endroit là.
    Si vous incluez un fichier .c imaginez les dégâts !
    Vous ne pouvez pas faire d'hypothèse sur l'ordre d'ajout des fichier .obj lors du link.
    La ligne #ifndef NOM veut dire "Est-ce qu'on a déjà vu NOM"
    La ligne #define NOM veut dire "Donc, je m'en souviendrai pour la prochaine fois"
    La ligne #endef veut dire fin du bloc #if...
    Dernière modification par Invité ; 02/11/2010 à 13h33.

  13. #13
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Chercheur d'emploi
    Inscrit en
    Septembre 2007
    Messages
    7 487
    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 487
    Par défaut
    Citation Envoyé par Pierre Dolez Voir le message
    La ligne #ifndef NOM veut dire "Est-ce qu'on a déjà vu NOM"
    Ça, c'est #ifdef.

    « #ifndef » signifie « If Not Defined » et signifierait plutôt dans ce contexte : « est-ce que c'est la première fois qu'on rencontre cette macro ? ».

  14. #14
    Invité
    Invité(e)
    Par défaut
    OK pardon

  15. #15
    Membre éclairé
    Profil pro
    Inscrit en
    Avril 2005
    Messages
    309
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2005
    Messages : 309
    Par défaut
    Les include incluent des fichiers d'entête (.h). C'est exactement comme si le code du fichier d'entête était écrit à cet endroit là.
    Si vous incluez un fichier .c imaginez les dégâts !
    Aaaahhh d'accord !!!! donc il ne faut jamais inclure un .c que des .h

    C'est quand meme dommage que le C n'ai pas prevu d'inclure des fichiers, comment dire..."texte", enfin des fichiers qui ne serait qu'une sorte de "morceau", ou de MACRO (J'suis pas sur de me faire comprendre )
    Une sorte de fichiers qui n'auraient aucune autre valeur pour le compilateur, que de justement s'inclure a l'endroit ou l'on met le #INCLUDE, au moment de la compilation, mais qui ne pourraient pas vraiment etre compilés seuls

    Bon je vais essayer de retenir votre leçon...donc jamais de .c en include, merci pierre

    « #ifndef » signifie « If Not Defined » et signifierait plutôt dans ce contexte : « est-ce que c'est la première fois qu'on rencontre cette macro ? ».
    Ce qui est bien dans les personnes comme moi qui n'y connaissent rien.....c'est que meme quand on leur dit l'inverse de ce qu'il devraient entendre, bah ils comprenent toujours de travers...
    Et le plus fou c'est que ça se remet dans le bon sens dans leur cerveau (Si tenté qu'il en ai un )

    En fait j'avais bien compris le contraire

    Merci à vous deux de vos reponses

  16. #16
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Chercheur d'emploi
    Inscrit en
    Septembre 2007
    Messages
    7 487
    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 487
    Par défaut
    Citation Envoyé par andrebernard Voir le message
    Le coup des includes...c'est encore pas simple a comprendre Surtout quand on y met les .h Et pourtant j'ai bien lu le TUTO :oops
    Voici quelques bases. D'abord, un peu de vocabulaire :

    — Une déclaration consiste à informer le compilateur de l'existence d'une entité quelconque. Déclarer une fonction, donc, consiste à écrire son prototype. De cette manière, le compilateur sait qu'elle existe et sait comment l'appeler, ce qui est tout ce qu'il lui faut. Le compilateur peut construire tout son code autour des appels à cette fonction, même si elle est externe. Le compilateur peut laisser en blanc l'adresse d'appel de cette fonction jusqu'au dernier moment ;

    — Une définition consiste à décrire le contenu de de cette entité au compilateur, justement pour qu'il la bâtisse. Dans le cas d'une fonction, cela se fait en écrivant son code. Pour une variable, c'est en lui affectant une valeur au moment où elle est déclarée.

    Ensuite, sur un plan purement formel, « #include » ne sert pas spécialement à utiliser une bibliothèque ou à lier son programme à un module, comme cela se voit dans d'autres langages. « #include » sert à insérer le contenu d'un fichier à l'endroit où cette directive est spécifiée. Le fichier en question peut lui-même contenir d'autres « #include », qui seront insérés à leur tour de la même façon. Le compilateur va passer de l'un à l'autre de manière tout-à-fait linéaire, comme s'il s'agissait d'un seul fichier.

    En fait, tu pourrais même écrire le début d'un appel à une fonction dans un fichier et le terminer dans un autre, le compilateur compilerait quand même. Par exemple :

    main.c
    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    /* Exemple à ne surtout pas suivre ! */
    #include <stdio.h>
     
    int main (void)
    {
        printf (
    #include "suite.c"
     
        return 0;
    };
    suite.c

    Qu'on ne te prenne jamais à écrire ce genre de chose, mais ça compile quand même. #include te permet donc d'inclure n'importe quoi, dans l'absolu.

    Maintenant, quand tu vas faire de la compilation séparée, soit parce que ton projet est très grand, soit parce que tu utilises des modules dont tu ne possèdes pas le code (ce qui sera pratiquement toujours le cas sauf dans le monde de l'Open Source et du logiciel libre), tu auras besoin, comme on l'a dit plus haut, du « mode d'emploi » de ce module, c'est-à-dire de la liste des entêtes de toutes les fonctions (les prototypes), donc leur headers. Et le moyen le plus simple pour faire cela, c'est de tous les regrouper dans un seul fichier « *.h », que tu incluras toi-même en début de fichier plutôt que les écrire à la main comme je te l'ai fait faire (à tort) dans une autre discussion. Ceci va te permettre de construire ton code, mais ce n'est pas pour cela qu'il va être associé à ce stade à la bibliothèque en question.

    C'est exactement le même cheminement que lors de la fabrication d'une automobile : tu ne fabriques pas celle-ci en la dégageant en un seul morceau d'un grand bloc de matière première.

    À la place, tu vas concevoir individuellement un certain nombre de pièces. Une fois que c'est fait, tu embauches une armée de tourneurs-fraiseurs, chacun équipé d'une machine-outil, d'un bloc de matière première, et d'un contrat de phase. Toutes les pièces sont fabriquées en parallèle en portant une attention particulière aux tolérances concernant les extrémités des pièces et leurs points d'ancrage avec les autres pièces (l'interface). Une fois toutes les pièces produites, tu les assembles et tu obtiens un véhicule en état de rouler.

    Tu vas faire la même chose avec tes différentes unités de compilation. Elles vont toutes compiler en un *.o distinct.


    Pourquoi, maintenant, n'inclut-on jamais, en pratique, de fichier *.c à partir d'un autre ? D'abord pour les raisons exposées plus haut, ensuite, parce que tu ne peux pas toujours le faire (tu ne disposes pas du code), et enfin, parce qu'on s'efforce autant que possible, d'éviter de tout re-compiler à la moindre modification, ce qu'une inclusion de sources t'obligerait à faire.

    C'est peut-être une notion abstraite quand on écrit son premier « Hello World », mais imagine que la totalité de Windows doive être recompilée à la moindre faute d'orthographe repérée ! Il y en aurait pour des heures au minimum, voire des jours, et c'était d'autant plus vrai sur les machines de 1972.

  17. #17
    Membre éclairé
    Profil pro
    Inscrit en
    Avril 2005
    Messages
    309
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2005
    Messages : 309
    Par défaut
    Tout d'abord merci de cette belle explication détaillée et surtout de ta patience
    Parce qu'avec moi....y'en faut...j'suis capable de prendre une baigne de la propre main du prix nobel de la paix

    « #include » sert à insérer le contenu d'un fichier à l'endroit où cette directive est spécifiée. Le fichier en question peut lui-même contenir d'autres « #include », qui seront insérés à leur tour de la même façon. Le compilateur va passer de l'un à l'autre de manière tout-à-fait linéaire, comme s'il s'agissait d'un seul fichier.
    Et bien c'est justement ce que cherchais a faire, juste inserer un code dans un autre a la place de #include

    Bon alors y'a une finesse qui doit m'echapper

    Alors je ne fait pas de include pour pas avoir a tout recompiler comme tu le dit.
    Au passage j'aurais jamais imaginé qu'il faille plusieurs heures pour compiler certains codes

    Je met donc mes fonctions classées dans chaque .c comme je l'avais expliqué au dessus
    Un pour gérer les dossiers/fichiers
    Un pour gérer le graphisme
    Un pour mes modules de cryptage
    Un pour la gestion du texte
    Etc...

    Je me retrouve donc avec tous ces fichiers et dedans toutes mes fonctions qui sont de la meme famille

    Je créé donc un ".h" de chaque fichier .c avec toutes les declarations (Prototypes) de chacune des fonctions de chaque ".c" (j'espere que au moins jusque la....j'ai compris )

    Voila deja la premiere question dans ma tete qui pointe le bout de son groin

    1/ Comment le compilateur y sait quel .h va avec quel .c ???
    Est ce que les noms ont une importance, c'est a dire doit on exactement nommer un .h comme son .c

    Bon je me retrouve avec donc X ".h" et X ".c", bon voila la soeur de la premiere question qui arrive

    2/ Le C commence toujours par la fonction WinMain, (En version "fenetre"), bon d'accord
    Mais comment je fais pour declarer tous mes .h dans mon projet ???
    Je les mets tous au dessus du WinMain ???

    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
    #include <windows.h>
    #include "Cryptage.h"
    #include "Graphisme.h"
    #include "DossierFichier.h"
    etc ....
    etc ....
     
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
    {
     
     // Create first class
     ClassRegister(hInstance, nCmdShow);
     
      // Create the windows
    	return OuvertureFenetre(hInstance, nCmdShow);
    etc....
    etc ....
    C'est la que je suis perdu
    Je comprend pas comment il se debrouille pour faire sa soupe le compilateur

  18. #18
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Chercheur d'emploi
    Inscrit en
    Septembre 2007
    Messages
    7 487
    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 487
    Par défaut
    Citation Envoyé par andrebernard Voir le message
    Et bien c'est justement ce que cherchais a faire, juste inserer un code dans un autre a la place de #include
    Comme on l'a dit, le #include est complètement en dehors des considérations morales sur ce point. Il peut être justifié d'insérer directement du code dans certains cas, mais c'est très rare, et il s'agit souvent, en fait, de définitions de variables ou de données générées par un script. Le meilleur exemple que je connaisse en la matière est le format d'image *.xpm de X-Window, que je te suggère de laisser de côté pour le moment.

    Alors je ne fait pas de include pour pas avoir a tout recompiler comme tu le dit. Au passage j'aurais jamais imaginé qu'il faille plusieurs heures pour compiler certains codes
    Essaie de recompiler le projet GNOME depuis zéro, pour voir ! Moi, j'ai essayé, et je m'en souviens encore.

    Je met donc mes fonctions classées dans chaque .c comme je l'avais expliqué au dessus
    Un pour gérer les dossiers/fichiers
    Un pour gérer le graphisme
    Un pour mes modules de cryptage
    Un pour la gestion du texte
    Etc...

    Je me retrouve donc avec tous ces fichiers et dedans toutes mes fonctions qui sont de la meme famille.
    Ok.

    Je créé donc un ".h" de chaque fichier .c avec toutes les declarations (Prototypes) de chacune des fonctions de chaque ".c" (j'espere que au moins jusque la....j'ai compris ) Voila deja la premiere question dans ma tete qui pointe le bout de son groin

    1/ Comment le compilateur y sait quel .h va avec quel .c ???
    Il ne le sait pas, et il n'a pas besoin de le savoir. C'est ça qui est bien avec le C. Tu restes complètement maître de l'organisation de ton code (Java, par exemple, t'impose d'utiliser un fichier par classe, qui en plus doit porter le même nom).

    Tout ce qu'il faut, c'est que les déclarations soient faites au bon moment à la lecture du code, peu importe comment (d'un point de vue technique, bien sûr).

    Est ce que les noms ont une importance, c'est a dire doit on exactement nommer un .h comme son .c
    C'est une règle de bonne conduite (et de bon sens), mais ce n'est pas une obligation technique. En outre, un même *.h peut couvrir plusieurs fichiers *.c.

    Bon je me retrouve avec donc X ".h" et X ".c", bon voila la soeur de la premiere question qui arrive

    2/ Le C commence toujours par la fonction WinMain, (En version "fenetre"), bon d'accord
    Oulala, « WinMain », c'est exclusivement sous Windows. Ne prends pas d'emblée ce genre de référence. Le point d'entrée d'un programme C s'appelle main()

    Mais comment je fais pour declarer tous mes .h dans mon projet ???
    Je les mets tous au dessus du WinMain ???
    Tu ne « déclares » pas tes *.h, tu les inclus dans ton fichier à l'aide d'une directive. Ces fichiers inclus, eux, contiennent des déclarations (en principe).

    L'usage veut effectivement que les #include de tous ces fichiers soient regroupés en tête de fichier, avant la rédaction de ton propre code.

    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
    #include <windows.h>
    #include "Cryptage.h"
    #include "Graphisme.h"
    #include "DossierFichier.h"
    etc ....
    etc ....
     
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
    {
     
     // Create first class
     ClassRegister(hInstance, nCmdShow);
     
      // Create the windows
    	return OuvertureFenetre(hInstance, nCmdShow);
    etc....
    etc ....
    C'est la que je suis perdu
    Je comprend pas comment il se debrouille pour faire sa soupe le compilateur
    Comme on te l'a dit plus haut, le compilateur va générer un fichier objet, c'est-à-dire un fichier contenant ton code compilé et les données que tu y a intégrées. Ce fichier objet n'est pas exploitable en l'état par l'utilisateur. Il contient « des pièces ». C'est l'éditeur de liens (linker) qui, passant derrière ton compilo, va assembler toutes ces pièces entre elles, en faisant le bilan, pour chacun des fichiers objet, des ressources définies et des « trous » laissés en suspens, en tâchant de combler les trous de certains fichiers avec ce qu'il trouve dans les autres. Et si, une fois que toutes les associations sont faites, s'il trouve en plus un point d'entrée (une fonction main()), alors, par défaut, il crée un exécutable.

  19. #19
    Membre éclairé
    Profil pro
    Inscrit en
    Avril 2005
    Messages
    309
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2005
    Messages : 309
    Par défaut
    Oulala, « WinMain », c'est exclusivement sous Windows. Ne prends pas d'emblée ce genre de référence. Le point d'entrée d'un programme C s'appelle main()
    Ah pardon .... je croyais que c'etait obligatoire quand on faisait du windows et ses API

    Tout ce qu'il faut, c'est que les déclarations soient faites au bon moment à la lecture du code, peu importe comment (d'un point de vue technique, bien sûr).
    Et c'est la qu'est l'os helas
    J'ai mes .c classés, mais dans lequel je met mes includes ???
    Dans celui qui possede la fonction WinMain() ou Main() ??
    C'est ça que j'arrive pas a comprendre malgré le mal que vous vous donnez

    En VB par exemple, on se pose pas cette question, y'a un "reglage" pour le projet qui dit: "Tu commences par cette fonction"
    Ou bien tu commence par cette fenetre et hop on met le code dans le FormLoad
    C'est on pourrait dire le point d'entrée, apres..evidemment quand on appelle une fonction on en ressort, et roule ma poule, etc ...

    Mais la...comme tous mes .c y sont sur le meme plan, comment y sait le compilateur qu'il faut qu'il commence par un de ceux la ???

    J'ai bien compris que chaque .c est independant, et genere un obj...
    Mais justement comme ils sont independants faut bien que y'en ai un qui dise comme a la cantine quand on etait petit : "C'est moi le prem's non ???"

  20. #20
    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
    1/ Comment le compilateur y sait quel .h va avec quel .c ???
    Est ce que les noms ont une importance, c'est a dire doit on exactement nommer un .h comme son .c
    Le compilateur ne fait pas d'association .c <-> .h . Un include ne fait qu'insérer le texte du fichier inclus à l'emplacement du #include

    Par exemple, tu as créé un .c pour le graphisme. Appelons le Graphisme.c. Il contient toutes les fonctions nécessaires pour faire ce travail. Parmi ces fonctions, certaines doivent être utilisées par d'autres X.c. Pour être utilisables correctement par les autres X.c, il faut que ceux-ci connaissent leur prototype. On va donc créer un .h associé à Graphisme.c. Son nom n'a pas d'importance mais, pour s'y retrouver, il est bigrement commode qu'il prenne le nom du .c associé avec l'extension .h (désignant traditionnellement un fichier d'en-tête). Appelons le donc Graphisme.h.

    Dans ce fichier d'en-tête, on va mettre tout ce dont a besoin un X.c pour utiliser les fonctions de Graphisme.c (prototype de fonctions, déclarations de type, définition de constantes,...) et uniquement cela. En général, Graphisme.c fait un #include "Graphisme.h" pour éviter d'avoir à dupliquer toutes ces définitions.

    Pour tout X.c qui a besoin d'utiliser les fonctions de Graphisme.c (ou plus généralement les définitions de Graphisme.h), on fera un #include "Graphisme.h". Pour les autres, c'est inutile. (Si le X.c a lui-même un X.h, il est possible que le #include "Graphisme.h" soit à faire plutôt dans le X.h si celui-ci utilise des définitions figurant dans "Graphisme.h").

    Il ne faut pas tout mettre dans Graphisme.h. Par exemple, Graphisme.c a peut-être des fonctions faites pour être utilisées uniquement dans Graphisme.c. Celles-ci n'ont pas besoin d'être connues à l"extérieur" donc on ne mettra pas leur prototype dans le .h (et on les déclarera comme static). On ne mettra pas non plus de définitions de variables puisque comme il est possible que le .h soit inclus dans plusieurs .c on se retrouverait avec de multiples définitions de cette variable.

    y'a un "reglage" pour le projet qui dit: "Tu commences par cette fonction"
    En C, un programme commence toujours par la fonction qui s'appelle main() (winmain() dans ton code).

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. A propos des modèles d'objet (avec sources)
    Par DevX dans le forum C++Builder
    Réponses: 14
    Dernier message: 01/12/2002, 12h22
  2. [Crystal Report 8] créer une source de données oracle
    Par Lina dans le forum SAP Crystal Reports
    Réponses: 4
    Dernier message: 14/11/2002, 13h53
  3. Source Safe -> VC++
    Par Emilio dans le forum MFC
    Réponses: 7
    Dernier message: 07/11/2002, 15h57
  4. Outil de reformatage d'un source Pascal
    Par HRS dans le forum Pascal
    Réponses: 7
    Dernier message: 21/10/2002, 14h55
  5. mp3 et source
    Par davlefou dans le forum C
    Réponses: 2
    Dernier message: 18/10/2002, 15h01

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