1. #1
    Futur Membre du Club
    Profil pro
    Inscrit en
    mars 2013
    Messages
    16
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : mars 2013
    Messages : 16
    Points : 9
    Points
    9

    Par défaut Différence entre une définition et declaration (variable et structure)

    Bonjour,

    Suite a mon apprentissage du C, j'essaie d'utiliser les structures.

    Je vous met ici mon code de test.

    Mon Main
    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
    /* LIBRAIRIE */
    #include "stdlib.h"
    #include "stdio.h"
    #include "fonctions.h"
     
     
     
    int main(int argc, char *argv[]) {
     
        int i;
     
        struct sCoordonneePion
        {
            char cCharColonne;
            int dIntColonne;
            int dLigne;
            char tDamier[8][8];
        };
        //typedef struct sCoordonneePion sCoordonneePion;
     
        struct sCoordonneePion dFou, dTour;
     
        test(&dFou);
        printf("dLigne = %d", dFou.dLigne);
    }

    Mon fichier fonctions.h

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void test(struct sCoordonneePion *pdFou);

    et mon fichier fonction.c

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    void test(struct sCoordonneePion *pdFou)
    {
        pdFou->dLigne = 12;
     
    }

    Les erreurs que visual studio souligne en rouge dans le main :

    il souligne le & et me dit

    "L'argument de type "sCoordoneePion *" est incompatible avec le paramètre de type "sCoordonneePion *"

    Et l'erreur que j'ai dans le fichier "fonctions.cpp" :

    Visual Studio souligne en rouge pdFou et me dit :

    "Pointeur vers un type classe incomplète non autorisé"


    On m'a indiquer que je devais déclarer la structure dans mon fichier fonctions.h
    m’expliquant que je devais déclarer ma structure

    Oui, tu doit mettre la déclaration du type struct sCoordonneePion dans le .h. Mais seulement la déclaration du type, pas la définition des variables dFou, dTour.
    Je suppose que le cours que tu suis a mal présenté les notions de déclaration et définition. Elles sont simples, mais fondamentale. Une déclaration sert décrire un identificateur, ainsi le compilateur sait ce que représente cet identificateur (une fonction, un type, une variable, etc.). Mais une simple déclaration ne produit rien dans l'exécutable compilé. Ce qui produit qqch, c'est une définition.

    Quelques exemples :
    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
    // déclaration de type
    struct toto {
       int x;
       char y;
    };
     
    // déclaration de variable
    extern int foo;
     
    // déclaration de fonction
    int bar(void);
     
    // définition de variable
    int foo;
     
    // définition de fonction
    int bar(void) {
        return 22;
    }
    et j'avoue ne pas comprendre la différence..
    Est ce que qlq'un pourrait m'expliquer la différence svp??
    Ou me diriger vers un lien pertinent??! pq je ne trouve rien qui soit "parlant"..

    Merci d'avance a ceux qui prendront le temps de m’éclairer

  2. #2
    Membre émérite
    Inscrit en
    mars 2005
    Messages
    992
    Détails du profil
    Informations forums :
    Inscription : mars 2005
    Messages : 992
    Points : 2 901
    Points
    2 901

    Par défaut

    Ton type est déclaré au sein de main et sa visibilité est donc limitée à la portée de cette fonction. Pour qu'une autre portée s'en serve il faut déplacer la déclaration hors de tout corps de fonction et avant toute définition qui l'utilise.

    Deux remarques par rapport au développement avec Visual Studio :

    • ne fais pas une confiance aveugle à l'analyse de code « temps réel » (qui souligne les « erreurs » en rouge) : elle est parfois faillible ou en retard. Fies-toi aux messages du compilateur dans la console de sortie.
    • les fichiers sources portant l'extension .cpp sont compilés en C++ en l'absence de l'option /Tc. Si tu programmes en C comme ton message le suggère, renomme tes fichiers en .c .

  3. #3
    Expert confirmé
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    juillet 2013
    Messages
    1 986
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : juillet 2013
    Messages : 1 986
    Points : 4 339
    Points
    4 339

    Par défaut

    Matt_Houston ne répond pas à la question

    En gros, une déclaration c'est juste pour dire au compilateur que quelque chose existe et comment. Afin de faire des vérifications.

    Pour une fonction/ procédure, cela permet au compilateur de connaître la signature.
    Pour une variable, tu vas "créer" cette variable (1)
    À moins qu'elle soit externe, et donc le compilateur va savoir qu'il existe une variable quelque part de ce type avec ce nom.

    Donc toutes les déclarations sont mises dans les entêtes (fichier .h), sauf pour les variables (1). Parce que, sinon, tu vas créer plusieurs fois la même variable.
    Certaines déclarations peuvent être mises dans les sources (fichier .cpp): pour les variables (1), ou pour les rendre privé.

    Il y a aussi la notion de déclaration avancée (forward declaration)


    Et une définition de fonction/ procédure, c'est le corps.
    Elles sont quasi toutes mises dans les sources (fichier .cpp), sauf pour les petites fonctions/ procédures (qui peuvent être mises dans les entêtes)


    Édit: je me suis bourré Merci Matt_Houston

  4. #4
    Futur Membre du Club
    Profil pro
    Inscrit en
    mars 2013
    Messages
    16
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : mars 2013
    Messages : 16
    Points : 9
    Points
    9

    Par défaut

    D'abord merci

    Je comprend bien cela, mais pourquoi ca n'est pas le cas avec une variable "classique" alors?
    Quand je passe une variable "classique" a une fonction, je n'ai pas besoin de la déclarer ailleurs que dans mon main.. ??!!
    Et c'est ca que je ne comprend pas.. y a qlq chose qui m’échappe la dedans..

    Pour les fichiers en .cpp, c'est la deuxième fois que l'on me fait la remarque.. mais visual studio n'a pas d'option pour créer un projet console directement en .c
    Je vais jeter un oeil a ca..

  5. #5
    Membre émérite
    Inscrit en
    mars 2005
    Messages
    992
    Détails du profil
    Informations forums :
    Inscription : mars 2005
    Messages : 992
    Points : 2 901
    Points
    2 901

    Par défaut

    Citation Envoyé par foetus Voir le message
    Matt_Houston ne répond pas à la question
    Laquelle ? Qu'est-ce qu'une déclaration, une définition ? La réponse est paraphrasée dans le message même cité par l'OP, ici sur dvp et à des millions d'autres endroits. Je plaide coupable : en général j'essaie de faire cours pour mon premier message sur un fil.


    Citation Envoyé par foetus Voir le message
    Et une déclaration de fonction/ procédure, c'est le corps.
    Non c'est le contraire : une définition implique toujours une déclaration mais l'inverse est faux dans le cas général.

    Exemples de déclarations pures :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    // "j'annonce une variable de type 'int', nommée 'i'"
    extern int i;
     
    // "j'annonce un type agrégé nommé 'struct foo'"
    struct foo;
     
    // "j'annonce une fonction qui attend un pointeur vers un 'struct foo' et renvoie un 'int', nommée 'bar'"
    int bar(struct foo *); // ok, le compilateur n'a pas besoin de connaître sizeof(struct foo), seulement sizeof(struct foo *)
     
    // "j'annonce une fonction qui attend un 'struct foo' et renvoie un 'int', nommée 'bar2'"
    int bar2(struct foo); // /!\ erreur : le compilateur ne peut pas déterminer sizeof(struct foo)

    Exemples de définitions :

    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
    // "j'annonce une variable de type 'int', nommée 'i', et voici à quoi elle ressemble"
    int i;
     
    // "j'annonce un type agrégé nommé 'struct foo', et voici à quoi il ressemble"
    struct foo {
        int k;
    }; // le compilateur dispose désormais des informations nécessaires à l'évaluation de sizeof(struct foo) et de l'opérateur de déréférencement
     
    // "j'annonce une fonction qui attend un pointeur vers un 'struct foo' et renvoie un 'int', nommée 'bar', et voici à quoi elle ressemble"
    int bar(struct foo *f) {
        const int i = f->k; // le compilateur a préalablement besoin de la définition de 'struct foo' pour savoir qu'elle comporte un membre nommé 'k', de type 'int'
        f->k = 0;
        return i;
    }
     
    // "j'annonce une fonction qui attend un 'struct foo' et renvoie un 'int', nommée 'bar2', et voici à quoi elle ressemble"
    int bar2(struct foo f) {
        const int i = f.k; // le compilateur a préalablement besoin de la définition de 'struct foo' pour savoir qu'elle comporte un membre nommé 'k', de type 'int'
        f.k = 0; // pas d'effet en dehors de la portée locale, puisque f est une copie
        return i;
    }


    Citation Envoyé par Dunkhan Voir le message
    Je comprend bien cela, mais pourquoi ca n'est pas le cas avec une variable "classique" alors?
    Quand je passe une variable "classique" a une fonction, je n'ai pas besoin de la déclarer ailleurs que dans mon main.. ??!!
    Et c'est ca que je ne comprend pas.. y a qlq chose qui m’échappe la dedans..
    La procédure de compilation ne va pas reconstituer à la volée la pile d'appels de ton programme, en simulant le flux d'exécution, ça c'est pour un langage interprété. Il va traduire en langage machine chaque fonction de chaque module indépendamment de toutes les autres. test n'a pas « conscience » de l'existence de main, et main n'a pas besoin de savoir comment test effectue son traitement, simplement quoi lui passer et quoi en attendre. C'est la phase d'édition de liens, qui a lieu après la compilation, qui a la charge de lier les fonctions entre elles et de réaliser un ensemble exécutable cohérent.


    Citation Envoyé par Dunkhan Voir le message
    Pour les fichiers en .cpp, c'est la deuxième fois que l'on me fait la remarque.. mais visual studio n'a pas d'option pour créer un projet console directement en .c
    Je vais jeter un oeil a ca..
    Un IDE, et particulièrement Visual Studio (versions jusqu'à 2012), n'est pas l'idéal pour débuter en C. Je te recommande personnellement MSYS2. Jette un œil sur les forum C et C++, le sujet est abordé régulièrement.

  6. #6
    Futur Membre du Club
    Profil pro
    Inscrit en
    mars 2013
    Messages
    16
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : mars 2013
    Messages : 16
    Points : 9
    Points
    9

    Par défaut

    Merci beaucoup pour vos réponses

    Je comprend un peu mieux le pourquoi du comment.

    Je vais jeter un oeil a l'IDE conseillé, mais on utilise visual studio a l'école, et j'avoue aimer l'interface.. je suppose que mes gouts changerons au fil du temps..

  7. #7
    Membre émérite
    Inscrit en
    mars 2005
    Messages
    992
    Détails du profil
    Informations forums :
    Inscription : mars 2005
    Messages : 992
    Points : 2 901
    Points
    2 901

    Par défaut

    Le truc avec les IDE c'est que ce sont des logiciels destinés à la productivité, visant les programmeurs confirmés. Ce ne sont pas des outils d'apprentissage adaptés aux débutants. Ils abstraient et automatisent beaucoup d'aspects liés au modèle de compilation C qu'il est important de connaître pour maîtriser ce que l'on fait.

    Maintenant, ce n'est pas indispensable. Si tu veux continuer avec VS alors assure-toi bien d'avoir la dernière version et d'utiliser l'option /Tc, ou bien de basculer sur le compilateur clang (il me semble qu'il est disponible avec VS depuis la version 2015) qui est probablement plus strict et plus à jour sur le C. Le C++ est un langage bien différent.

  8. #8
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    septembre 2005
    Messages
    26 345
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : septembre 2005
    Messages : 26 345
    Points : 37 717
    Points
    37 717

    Par défaut

    De plus, pour le langage C sous Visual Studio, il faut au minimum Visual Studio 2015 si tu veux faire quoi que ce soit de correct. Tous les précédents sont obsolètes de quinze ans.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

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

Discussions similaires

  1. différence entre une variable de session et une hashtable
    Par Gilllouman dans le forum ASP.NET
    Réponses: 8
    Dernier message: 13/09/2010, 11h54
  2. Différence entre une variable $toto et ${toto}
    Par nono27200 dans le forum Shell et commandes POSIX
    Réponses: 2
    Dernier message: 12/12/2008, 09h01
  3. [9iR2] Différence entre une table et une table objet ?
    Par mainecoon dans le forum Oracle
    Réponses: 1
    Dernier message: 16/02/2006, 04h28
  4. Réponses: 2
    Dernier message: 03/10/2005, 11h18
  5. Réponses: 2
    Dernier message: 25/05/2005, 21h34

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