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 :

Inclure plusieurs fichiers : double inclusion ?


Sujet :

C

  1. #1
    Nouveau membre du Club
    Homme Profil pro
    Lycéen
    Inscrit en
    Juillet 2012
    Messages
    34
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Lycéen
    Secteur : Enseignement

    Informations forums :
    Inscription : Juillet 2012
    Messages : 34
    Points : 31
    Points
    31
    Par défaut Inclure plusieurs fichiers : double inclusion ?
    Bonjour,

    J'ai un fichier main.cpp (je suis sous code::blocks, et il met l'extension .cpp lors de la création d'un projet SDL, mais c'est quand même du C), un fichier personnages.c, et un fichier personnages.h

    J'ai besoin d'une fonction (qui est dans personnages.c) dans main(), j'include donc mon fichier personnages.h (qui contient des external int)

    MAIS cette fonction a besoin de variables qui se trouvent dans main(), il faudrait donc que j'include le main.cpp dans personnages.c.

    Je vois pas trop comment faire, dois-je créer un main.h qui contient le prototype de main() et include ce main.h dans personnages.c ?
    Mais dans ce cas la, j'aurais une double inclusion --> donc erreur
    SAUF si je fais un #ifndef, mais vers ce moment là, je suis un peu perdu : ou dois-je faire mes #ifndef ???

    Pouvez vous m'aider SVP ?
    Merci beaucoup !

  2. #2
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 012
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 012
    Points : 23 145
    Points
    23 145
    Par défaut
    Bonjour,

    Tu sembles utiliser des variables globales, essaye déjà de les éviter au maximum.

    Sinon, en cas de problème, on utilise souvent des déclarations anticipées, exemple : struct MaStruct;
    cf code ci-dessous :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    #ifndef TOTO
     
    struct X; //pour les structures contenu dans foo
    extern int i; //pour les variables globales contenu dans foo (c'est le maaal :aie:)
     
    //mes prototypes
     
    struct Z{... };
     
    #endif
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    //TOTO.c
    #include "toto.h"
    #include "foo.h"
     
    //code des fonctions
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    #ifndef FOO
     
    struct Z;
    struct X{... };
    int i;
     
    //mes prototypes
     
    #endif
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    //foo.c
    #include "foo.h"
    #include "toto.h"
     
    //code des fonctions

  3. #3
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

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

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 481
    Points : 13 679
    Points
    13 679
    Billets dans le blog
    1
    Par défaut
    J'ai un fichier main.cpp (je suis sous code::blocks, et il met l'extension .cpp lors de la création d'un projet SDL, mais c'est quand même du C), un fichier personnages.c, et un fichier personnages.h
    Soit on fait du C, soit on fait du C++. Si on fait du langage X, on les mets dans des fichiers de type X. C'est le genre de trucs à perdre les lecteurs, risquer que d'autres personnes y mettent du code C++ non compatible avec du C, induire en erreur ton compilateur qui voyant *.cpp pourrait appeler g++ et non gcc....

  4. #4
    Nouveau membre du Club
    Homme Profil pro
    Lycéen
    Inscrit en
    Juillet 2012
    Messages
    34
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Lycéen
    Secteur : Enseignement

    Informations forums :
    Inscription : Juillet 2012
    Messages : 34
    Points : 31
    Points
    31
    Par défaut Reformulation
    Je n'utilise pas de variables globales, mes "external int" sont des fonctions
    de type :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    external int fonction(int a, int b)
    Donc, finalement, la question est plus une question du type :

    "Comment puis-je inclure deux fichiers si chacun à besoin de l'autre ?"

    Il me semble avoir lu qu'on ne doit jamais inclure des .c, mais si j'inclus personnages.h dans mon .cpp, il me met une erreur du type :
    "Erreur : [variable] is not declared on the scope"

    @Bktero : code::blocks attribue automatiquement un main.cpp au projet lors de la création d'un projet SDL. Comment changer les options de code::blocks pour qui'l crée un main.c à la place alors ??

    Merci !

  5. #5
    Membre expérimenté Avatar de Ngork
    Homme Profil pro
    Barbare IT
    Inscrit en
    Avril 2009
    Messages
    160
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Barbare IT
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2009
    Messages : 160
    Points : 1 372
    Points
    1 372
    Par défaut
    Citation Envoyé par totocaracana Voir le message
    Donc, finalement, la question est plus une question du type :
    "Comment puis-je inclure deux fichiers si chacun à besoin de l'autre ?"
    Tu ne peux pas !
    Par contre, ainsi que tu le proposais, tu peux créer un fichier main.h (c'est un peu vilain quand même mais bon, pourquoi pas ?) et un personnages.h qui seront tous deux inclus dans main.c et dans personnages.c.
    Puis, pour éviter les ennuis, tu tapes en en-tête de ton fichier main.h :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    #ifndef MAIN_H
    #define MAIN_H
     
    /// ici tes déclarations pour main
     
    #endif
    Et tu fais pareil pour personnages.h :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    #ifndef PERSO_H
    #define PERSO_H
     
    /// ici tes déclarations pour personnages
     
    #endif
    C'est tout !

  6. #6
    Membre expérimenté Avatar de Ngork
    Homme Profil pro
    Barbare IT
    Inscrit en
    Avril 2009
    Messages
    160
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Barbare IT
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2009
    Messages : 160
    Points : 1 372
    Points
    1 372
    Par défaut (bis)
    code::blocks attribue automatiquement un main.cpp au projet lors de la création d'un projet SDL. Comment changer les options de code::blocks pour qui'l crée un main.c à la place alors ??
    Tu ne peux pas, sauf à réécrire un wizard !

    MAIS ... tu peux soit créer un projet vide (c'est ce que je fais) et le configurer à la main, soit tu peux renommer ton main.cpp en main.c ... ET faire un clic droit sur ton fichier main.c dans Code::Blocks, afficher les propriétés (Properties) puis choisir l'onglet Avancé (Advanced) et remplacer CPP par CC pour que ce soit bien compilé par gcc et non par g++.

  7. #7
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 012
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 012
    Points : 23 145
    Points
    23 145
    Par défaut
    Citation Envoyé par totocaracana Voir le message
    Je n'utilise pas de variables globales, mes "external int" sont des fonctions
    de type :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    external int fonction(int a, int b)
    Pour moi un int est une variable et non une fonction
    Si tu veux être compris, soit plus précis, c'est une fonction retournant un int.
    D'ailleurs le bon mot clé n'est-il pas extern ?

    De plus cela fait quelques temps que je programme et je n'ai encore jamais eu à utiliser extern pour déclarer des fonctions, généralement on se contente de mettre le prototype dans un .h, le code dans un .c puis d'inclure le .h partout où on a besoin de la fonction.

    Citation Envoyé par totocaracana Voir le message
    Il me semble avoir lu qu'on ne doit jamais inclure des .c, mais si j'inclus personnages.h dans mon .cpp, il me met une erreur du type :
    "Erreur : [variable] is not declared on the scope"
    On ne peut pas vraiment voir ce que tu fais, pourrais-tu nous montrer ces fichiers?

    Citation Envoyé par totocaracana Voir le message
    @Bktero : code::blocks attribue automatiquement un main.cpp au projet lors de la création d'un projet SDL. Comment changer les options de code::blocks pour qui'l crée un main.c à la place alors ??
    Au pire rien ne t'empêche de créer un projet vide.

  8. #8
    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
    Salut,

    Citation Envoyé par totocaracana Voir le message
    Comment changer les options de code::blocks pour qui'l crée un main.c à la place alors ??
    Euh... Peut-être en ne cliquant pas trop vite dans le wizard? La deuxième page propose le choix entre C et C++, avec C++ par défaut. Du coup si on choisit C, on a bien un main.c créé dans le projet.

    A+

    Pfeuh
    Images attachées Images attachées  

  9. #9
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

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

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 481
    Points : 13 679
    Points
    13 679
    Billets dans le blog
    1
    Par défaut
    D'ailleurs le bon mot clé n'est-il pas extern ?

    De plus cela fait quelques temps que je programme et je n'ai encore jamais eu à utiliser extern pour déclarer des fonctions
    Le mot-clé en effet extern. J'ai souvenir que les fonctions étaient externes par défaut et qu'il était donc inutile de le préciser. C-Faq dit simplement que ce mot-clé ne s'applique pas aux fonctions : http://c-faq.com/decl/extern.html

  10. #10
    Membre expérimenté Avatar de Ngork
    Homme Profil pro
    Barbare IT
    Inscrit en
    Avril 2009
    Messages
    160
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Barbare IT
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2009
    Messages : 160
    Points : 1 372
    Points
    1 372
    Par défaut
    Citation Envoyé par pfeuh Voir le message
    Euh... Peut-être en ne cliquant pas trop vite dans le wizard? La deuxième page propose le choix entre C et C++, avec C++ par défaut. Du coup si on choisit C, on a bien un main.c créé dans le projet.
    Pour un nouveau projet de type console par exemple, tu as raison, mais j'insiste sur le fait que ce choix n'est pas proposé dans le wizard d'un nouveau projet SDL qui ne montre pas cette page de choix et va directement à la détermination de l'emplacement et du nom du projet puis impose un fichier main.cpp ...

  11. #11
    Nouveau membre du Club
    Homme Profil pro
    Lycéen
    Inscrit en
    Juillet 2012
    Messages
    34
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Lycéen
    Secteur : Enseignement

    Informations forums :
    Inscription : Juillet 2012
    Messages : 34
    Points : 31
    Points
    31
    Par défaut
    Merci pour toutes ces reponses !

    Pour les external, je changerai donc par extern, mais ce n'est pas ça qui posait problème ...

    Je vais suivre la méthode de Ngork, je pense.
    Je publierai mes sources demain, je ne peux pas pour l'instant, désolé.

    Pour les histoires de cpp/c, mes projets SDL ont toujours marché, et j'avoue qu'à mon niveau je ne me pose pas trop de questions, je m'en poserais plus tard

    Juste une derniere quesiton :
    #ifndef MAIN_H
    #define MAIN_H

    /// ici tes déclarations pour main

    #endif
    Qu'entendez vous par "déclarations pour main" ???
    Est-ce mes prototypes, les variables utilisée ? Je suis dans le flou total concernant ce point.

    Merci !

  12. #12
    Membre expérimenté Avatar de Ngork
    Homme Profil pro
    Barbare IT
    Inscrit en
    Avril 2009
    Messages
    160
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Barbare IT
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2009
    Messages : 160
    Points : 1 372
    Points
    1 372
    Par défaut
    Citation Envoyé par totocaracana Voir le message

    Juste une derniere quesiton :

    Qu'entendez vous par "déclarations pour main" ???
    Est-ce mes prototypes, les variables utilisée ? Je suis dans le flou total concernant ce point.

    Merci !
    Un exemple valant mieux qu'un long discours, voici un exemple (sans intérêt autre que de servir d'exemple) d'un fichier main.c qui fait appelle à une fonction déclarée dans un autre fichier (personnages.h) et implémentée dans un autre encore (personnages.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
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
     
    #include "main.h"
    #include "personnages.h"
     
     
    int main()
    {
        strcpy(texte_main,"Salut totocaracana !");
     
        afficher_texte();
     
        getchar();
     
        return 0;
    }
    Puis de son fichier d'entête main.h, qui contient la déclaration des variables de main utilisées dans personnages.c :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    #ifndef MAIN_H
    #define MAIN_H
     
    char texte_main[100];
     
    #endif
    Puis, voici le fichier personnages.h, qui contient la déclaration de la fonction afficher_texte() utilisée dans main.c :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    #ifndef PERSO_H
    #define PERSO_H
     
    void afficher_texte(void);
     
    #endif
    Et enfin, le fichier personnages.c qui implémente la fonction afficher_texte, fonction qui utilise la variable texte_main déclarée dans main.h :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    #include <stdio.h>
    #include <stdlib.h>
     
    #include "main.h"
    #include "personnages.h"
     
     
    void afficher_texte(void)
    {
        printf("%s\n",texte_main);
    }
    Si tu compiles tout ça ensemble, tu obtiendras un exécutable qui t'affichera joyeusement : Salut totocaracana !

  13. #13
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

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

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 481
    Points : 13 679
    Points
    13 679
    Billets dans le blog
    1
    Par défaut
    Qu'entendez vous par "déclarations pour main" ???

    Est-ce mes prototypes, les variables utilisée ? Je suis dans le flou total concernant ce point.
    Souviens-toi de ce que peut (doit ?) contenir un fichier d'en-tête : les prototypes de fonctions, les définitions de types, les inclusions d'autres fichiers d'en-tête, des macros et, pour les variables, uniquement leurs déclarations externes. Un fichier d'en-tête ne doit pas contenir de "vrai" code, c'est-à-dire pas de définition de fonction, de déclaration / définition de variable (sans le mot-clé extern, j'entends).

    EDIT : arghhh !! Heureusement que je relis Ngork après avoir posté !
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    #ifndef MAIN_H
    #define MAIN_H
     
    char texte_main[100];
     
    #endif
    Non ! Ca doit être dans le main.c ! main.h doit contenir la déclaration avec extern


    EDIT bis : en relisant un peu le sujet, je pense que le problème vient de là :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    MAIS cette fonction a besoin de variables qui se trouvent dans main(), il faudrait donc que j'include le main.cpp dans personnages.c.
    Et c'est ce que traduit le code très bizarre de Ngork. Pour moi, il y a probablement ici une erreur de conception. Chaque module devrait être indépendant des autres. Ici, il faut certainement mettre un paramètre supplémentaire à la fonction plutôt que d'utiliser les variables globales. Des fois, ce n'est pas possible, mais tant que tu peux t'en passer, fais-le. Tu éviteras notamment ce genre de problèmes.

  14. #14
    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 Ngork Voir le message
    un nouveau projet SDL
    Ah, j'ai raté cette info. j'ai eu le problème aussi. En général je fais un remove file from project (click droit sur main.cpp), je fais un add file (click droit sur le projet). La fenêtre du sélecteur de fichiers s'ouvre, j'en profite pour y renommer directement main.cpp en main.c, puis je l'ajoute au projet. Il suffit ensuite de remplacer son texte par celui qui est ci-dessous et le tour est joué.

    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
    #ifdef __cplusplus
        #error Should normaly use a C compiler
    #endif
     
    #ifdef __APPLE__
        #include <SDL/SDL.h>
    #else
        #include <SDL.h>
    #endif
     
    #include <stdlib.h>
    #include <stdbool.h>
     
    int main ( int argc, char** argv )
    {
        SDL_Event event;
        SDL_Surface* screen;
        SDL_Surface* bmp;
        SDL_Rect dstrect;
        bool done = false;
     
        /* initialize SDL video */
        if ( SDL_Init( SDL_INIT_VIDEO ) < 0 )
        {
            printf( "Unable to init SDL: %s\n", SDL_GetError() );
            return 1;
        }
     
        /* make sure SDL cleans up before exit */
        atexit(SDL_Quit);
     
        /* create a new window */
        screen = SDL_SetVideoMode(640, 480, 16, SDL_HWSURFACE|SDL_DOUBLEBUF);
        if ( !screen )
        {
            printf("Unable to set 640x480 video: %s\n", SDL_GetError());
            return 1;
        }
     
        /* load an image */
        bmp = SDL_LoadBMP("cb.bmp");
        if (!bmp)
        {
            printf("Unable to load bitmap: %s\n", SDL_GetError());
            return 1;
        }
     
        /* centre the bitmap on screen */
        dstrect.x = (screen->w - bmp->w) / 2;
        dstrect.y = (screen->h - bmp->h) / 2;
     
        /* program main loop */
        while (!done)
        {
            /* message processing loop */
            while (SDL_PollEvent(&event))
            {
                /* check for messages */
                switch (event.type)
                {
                    /* exit if the window is closed */
                case SDL_QUIT:
                    done = true;
                    break;
     
                    /* check for keypresses */
                case SDL_KEYDOWN:
                    {
                        /* exit if ESCAPE is pressed */
                        if (event.key.keysym.sym == SDLK_ESCAPE)
                            done = true;
                        break;
                    }
                } /* end switch */
            } /* end of message processing */
     
            /* DRAWING STARTS HERE */
     
            /* clear screen */
            SDL_FillRect(screen, 0, SDL_MapRGB(screen->format, 0, 0, 0));
     
            /* draw bitmap */
            SDL_BlitSurface(bmp, 0, screen, &dstrect);
     
            /* DRAWING ENDS HERE */
     
            /* finally, update the screen :) */
            SDL_Flip(screen);
        } /* end main loop */
     
        /* free loaded bitmap */
        SDL_FreeSurface(bmp);
     
        /* all is well ;) */
        printf("Exited cleanly\n");
        return 0;
    }
    A+

    Pfeuh

  15. #15
    Nouveau membre du Club
    Homme Profil pro
    Lycéen
    Inscrit en
    Juillet 2012
    Messages
    34
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Lycéen
    Secteur : Enseignement

    Informations forums :
    Inscription : Juillet 2012
    Messages : 34
    Points : 31
    Points
    31
    Par défaut Récapitulatif
    Donc finalement, la meilleure solution serait de prendre un grand nombre de variables en parametres pour ne plus être embêté ?

    J'aurais pas vu ça comme ça, mais ça marche !!!
    [Résolu] donc

    Merci à vous tous
    Totocaracana

  16. #16
    Membre expérimenté Avatar de Ngork
    Homme Profil pro
    Barbare IT
    Inscrit en
    Avril 2009
    Messages
    160
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Barbare IT
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2009
    Messages : 160
    Points : 1 372
    Points
    1 372
    Par défaut
    Citation Envoyé par Bktero Voir le message
    EDIT : arghhh !! Heureusement que je relis Ngork après avoir posté !
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    #ifndef MAIN_H
    #define MAIN_H
     
    char texte_main[100];
     
    #endif
    Non ! Ca doit être dans le main.c ! main.h doit contenir la déclaration avec extern


    EDIT bis : en relisant un peu le sujet, je pense que le problème vient de là :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    MAIS cette fonction a besoin de variables qui se trouvent dans main(), il faudrait donc que j'include le main.cpp dans personnages.c.
    Et c'est ce que traduit le code très bizarre de Ngork. Pour moi, il y a probablement ici une erreur de conception. Chaque module devrait être indépendant des autres. Ici, il faut certainement mettre un paramètre supplémentaire à la fonction plutôt que d'utiliser les variables globales. Des fois, ce n'est pas possible, mais tant que tu peux t'en passer, fais-le. Tu éviteras notamment ce genre de problèmes.
    J'ai simplement suivi les indications particulières de totocaracana !

    Je n'ai pas écrit que je coderais comme cela pour un projet personnel ... toutefois, je maintiens que le code proposé respecte strictement les indications de totocaracana, compile et fonctionne parfaitement, ne présente aucune anomalie (il n'y a d'ailleurs aucune alerte lors de la compilation car la variable n'est bien sûr pas initialisée dans le header mais dans le main.c) et est facile à maintenir !

    Alors, pourquoi pas ?

  17. #17
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

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

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 481
    Points : 13 679
    Points
    13 679
    Billets dans le blog
    1
    Par défaut
    Donc finalement, la meilleure solution serait de prendre un grand nombre de variables en parametres pour ne plus être embêté ?
    Si tu as besoin d'un grand nombre de variables en paramètres, ça peut être encore signe d'une mauvaise conception ^^ Dure la vie je sais. Normalement, une fonction ne devrait pas avoir beaucoup de paramètres. Le terme beaucoup est relatif... Je lis en ce moment Code Complete et il donne le chiffre de 7. Je trouve ça presque déjà beaucoup. Regarde si tu ne peux pas simplifier, découper en plusieurs fonctions, faire des structures, etc.


    Je n'ai pas écrit que je coderais comme cela pour un projet personnel ... toutefois, je maintiens que le code proposé respecte strictement les indications de totocaracana,
    Je ne t'ai en aucun cas accusé ! C'est juste que ce code est bizarre et m'a fait réfléchir au pourquoi.

    compile et fonctionne parfaitement, ne présente aucune anomalie (il n'y a d'ailleurs aucune alerte lors de la compilation car la variable n'est bien sûr pas initialisée dans le header mais dans le main.c) et est facile à maintenir !
    J'ai fait pas mal de tests avant de comprendre, en me rappelant une conversation que j'avais eu ici (avec Neckara peut-être bien ?). Ça marche, mais c'est prendre une très mauvaise habitude.

    Regardons le code suivant :
    int a;
    int a;
    Tu mets ça dans un fichier, il compile sans problème. En effet, quand tu redéclares une variable globale, le compilateur ne t'embête pas. Si au lieu de mettre les 2 lignes dans le même fichier, tu en mets une dans 2 fichiers, même effet : pas d'erreur de compilation et pas d'erreur d'édition des liens.

    En revanche, si tu mets ça dans un seul fichier, tu auras une erreur de compilation , ça ne marche évidemment pas. :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    int a = 2;
    int a = 2;
    Si tu mets une ligne de ces lignes dans 2 fichiers, tu auras aussi une erreur mais d'édition des liens. Cette fois, linker et compilateur ne sont pas capables de comprendre que c'est la même variable.

    Pour en revenir à ce code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    #ifndef MAIN_H
    #define MAIN_H
     
    char texte_main[100];
     
    #endif
    Tu te prives ainsi de toute initialisation de tes variables (elles seront à 0 ou NULL, comme toutes les variables globales et statiques non initialisées). Tu seras donc obligé de faire des fonctions pour initialiser les variables.

    Il vaut donc mieux déclarer les variables globales dans des fichiers .c (soit toutes dans une seule fichier, soit dans le fichier le plus logique) et inclure les déclarations externes là où on en a besoin.

    PS : une lecture très intéressante : http://c-faq.com/decl/decldef.html
    Il peut en effet y avoir plusieurs déclarations d'une variable globale.

    PS2 : je lis la norme C99, plus exactement la partie 6.2.2 Linkages of identifiers. Le point 4 me donne l'impression que le mot-clé extern est non obligatoire pour les variables. J'ai toujours crû que c'était obligatoire, pourtant, j'arrive à définir une variable dans main.c, à la déclarer sans extern dans personnages.c et ça linke sans soucis :s

    PS3 : c'était bien avec Neckara ^^http://www.developpez.net/forums/d12...ion-variables/

  18. #18
    Membre expérimenté Avatar de Ngork
    Homme Profil pro
    Barbare IT
    Inscrit en
    Avril 2009
    Messages
    160
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Barbare IT
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2009
    Messages : 160
    Points : 1 372
    Points
    1 372
    Par défaut
    Citation Envoyé par Bktero Voir le message
    Il vaut donc mieux déclarer les variables globales dans des fichiers .c (soit toutes dans une seule fichier, soit dans le fichier le plus logique) et inclure les déclarations externes là où on en a besoin.
    Cela me semble contradictoire avec le lien (très intéressant d'ailleurs) que tu donnes dans ton premier PS, non ?

    When you need to share variables or functions across several source files, you will of course want to ensure that all definitions and declarations are consistent. The best arrangement is to place each definition in some relevant .c file. Then, put an external declaration in a header (``.h'') file, and #include it wherever the declaration is needed. The .c file containing the definition should also #include the same header file, so the compiler can check that the definition matches the declarations.
    Or dans le code que j'ai proposé ici, j'ai très exactement suivi les principes exposés dans ce lien (sauf pour extern qui n'a dans ce cas précis - à mon avis - aucune utilité), principes excellents que je respecte d'ailleurs dans tous mes projets et qui rendent très faciles la maintenance et le partage des tâches (je suppose que quelqu'un, il ya de nombreuses années, avait dû m'énoncer ces principes ).

    Là où, à mon avis, le mini code que je propose va trop loin, mais c'est pour répondre aux contraintes de la question posée, c'est dans le fait de fournir un main.h ...

    Tel que je le conçois et l'utilise, le main.c est destiné à contenir uniquement la fonction principale (+ éventuellement quelques fonctions locales simples), de préférence courte et limitée en gros à la boucle des messages ou évènements à gérer, une sorte d'arbre de branchement sur les fonctions adéquates, déclarés et implémentés dans leurs .h et .c respectifs et dont le main.c inclut les .h !

    Bref, nous discutons, mais j'ai l'impression qu'en fait nous sommes à peu près d'accord, non ?

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

Discussions similaires

  1. Réponses: 2
    Dernier message: 22/07/2013, 11h50
  2. Inclure plusieurs fichiers js dans une page html
    Par verocv dans le forum Général JavaScript
    Réponses: 2
    Dernier message: 30/12/2008, 11h02
  3. inclusion en tete dans plusieurs fichiers
    Par john123 dans le forum ASP
    Réponses: 1
    Dernier message: 15/06/2007, 13h01
  4. [struts] utiliser plusieurs fichiers properties
    Par jaimepasteevy dans le forum Struts 1
    Réponses: 7
    Dernier message: 03/10/2003, 17h02
  5. Génerer automatiquement plusieurs fichier .doc
    Par brunovitch dans le forum QuickReport
    Réponses: 3
    Dernier message: 09/07/2002, 08h19

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