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 :

Problème avec un fonction qui modifis un tableau à l'aide d'un pointeur


Sujet :

C

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Août 2006
    Messages
    256
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 256
    Points : 91
    Points
    91
    Par défaut Problème avec un fonction qui modifis un tableau à l'aide d'un pointeur
    Bonjour tout le monde,

    Je veut faire un fonction qui modifis un tableau de char.
    Le tableau de char est déclaré dans la fonction WinMain, et la fonction est écrite dans un autre fichier que celui dans lequel est WinMain.
    J'ai donc essayé en envoyant l'adresse du tableau à la fonction puis de bosser avec les pointeurs dans la fonction, mais ça ne marche pas ... :

    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
     
    // La déclaration du tableau et l'appel de ma fonction dans WinMain :
     
        char listeLecteurs[27]={0};
     
        ListeLecteurs(LireValeur(), &listeLecteurs);
     
    // La fonction en question :
     
    void ListeLecteurs (int valeurRegistre, char *pointeur)
    {
            [...]
                    ++*pointeur[0];
            [...]
    }
    Donc, quand je veut faire une opération sur le tableau, le compilateur renvois :
    - dans la fonction : error: invalid type argument of `unary *'
    - dans le WinMain : error: cannot convert `char (*)[27]' to `char*' for argument `2' to `void ListeLecteurs(int, char*)'

    Quelle est mon erreur ?

    Merci.
    A+, Pierre.

  2. #2
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 379
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 379
    Points : 41 572
    Points
    41 572
    Par défaut
    L'étoile devant pointeur[0] est de trop.
    Le & devant ListeLecteurs est de trop.
    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.

  3. #3
    Membre régulier
    Profil pro
    Inscrit en
    Août 2006
    Messages
    256
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 256
    Points : 91
    Points
    91
    Par défaut
    Merci Médinoc.

    Pour l'adresse du tableau j'avais oublié que son nom pointais à l'adresse de la première valeur ... par contre, pour l'étoile, je ne comprend pas, normalement, pour accéder à la valeur à partir du pointeur, c'est bien *nomDuPointeur=.....; ? ou c'est différent parce que dans ce cas c'est un tableau ?

    Enfin, en appliquant les modifications que tu m'a dis, il ne veut pas compiler et ne renvoit pas d'erreur ni de warnings, voilà le log :
    Linking executable: .\Cache lecteur 2.exe
    obj\fonctions.o:fonctions.cpp: (.text+0x0): multiple definition of `LireValeur()'
    obj\main.o:main.cpp: (.text+0x0): first defined here
    obj\fonctions.o:fonctions.cpp: (.text+0x110): multiple definition of `ListeLecteurs(int, char*)'
    obj\main.o:main.cpp: (.text+0x110): first defined here
    collect2: ld returned 1 exit status
    Process terminated with status 1 (0 minutes, 0 seconds)
    0 errors, 0 warnings

    Merci.
    A+, Pierre.

  4. #4
    Membre régulier
    Profil pro
    Inscrit en
    Août 2006
    Messages
    256
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 256
    Points : 91
    Points
    91
    Par défaut
    Je viens de rajouter l'option "Produce debuging symbols" (-g) au compilateur, et maintenant il me donne des précisions sur l'erreur :

    D:\Fichiers\Programation C-C++\C\Cache lecteur 2\fonctions.cpp:6: multiple definition of `LireValeur()'
    obj\main.o: D:\Fichiers\Programation C-C++\C\Cache lecteur 2\fonctions.cpp:6: first defined here
    D:\Fichiers\Programation C-C++\C\Cache lecteur 2\fonctions.cpp:34: multiple definition of `ListeLecteurs(int, char*)'
    obj\main.o: D:\Fichiers\Programation C-C++\C\Cache lecteur 2\fonctions.cpp:34: first defined here
    :: === Build finished: 4 errors, 0 warnings ===

    Donc apparament, ce qui ne va pas c'est que j'aurais définis plusieurs fois les deux fonction ... Je ne vois pas d'où ça peut venir, j'ai inclus le fichier qui contient les fonctions dans celui où il y a la WinMain avec #include "fonctions.cpp", il n'y a qu'un fonction avec le même nom, et j'ai mis ça pour voir si il essayais de l'inclure plusieurs fois :
    #ifndef ABCD
    #define ABCD
    [les fonctions]
    #endif

    Donc, je ne vois pas d'où ça peut venir ... vous avez une idée ?

    Merci.
    A+, Pierre.

  5. #5
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par Pierre.g
    Pour l'adresse du tableau j'avais oublié que son nom pointais à l'adresse de la première valeur ... par contre, pour l'étoile, je ne comprend pas, normalement, pour accéder à la valeur à partir du pointeur, c'est bien *nomDuPointeur=.....; ? ou c'est différent parce que dans ce cas c'est un tableau ?
    Le paramètre est de type pointeur. Il permet d'accéder à la donnée soit avec *, soit avec des [], mais pas les deux !
    Enfin, en appliquant les modifications que tu m'a dis, il ne veut pas compiler et ne renvoit pas d'erreur ni de warnings, voilà le log :
    Linking executable: .\Cache lecteur 2.exe
    obj\fonctions.o:fonctions.cpp: (.text+0x0): multiple definition of `LireValeur()'
    obj\main.o:main.cpp: (.text+0x0): first defined here
    obj\fonctions.o:fonctions.cpp: (.text+0x110): multiple definition of `ListeLecteurs(int, char*)'
    obj\main.o:main.cpp: (.text+0x110): first defined here
    collect2: ld returned 1 exit status
    Process terminated with status 1 (0 minutes, 0 seconds)
    0 errors, 0 warnings
    Les fonctions sont définies plusieurs fois, ou inclues plusieurs fois. Montre tout ton code.

    Rappel :
    • Pour compiler en C, l'extension des sources est .c et non .cpp.
    • On n'inclue pas de .c
    • On ne définit pas de fonctions dans un .h
    Pas de Wi-Fi à la maison : CPL

  6. #6
    Rédacteur

    Avatar de millie
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    7 015
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 7 015
    Points : 9 818
    Points
    9 818
    Par défaut
    #include "fonctions.cpp",
    C'est à éviter absolument.
    Je ne répondrai à aucune question technique en privé

  7. #7
    Membre régulier
    Profil pro
    Inscrit en
    Août 2006
    Messages
    256
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 256
    Points : 91
    Points
    91
    Par défaut
    OK, merci pour ces réponses.

    Je savais bien qu'au niveau des inclusion il y a quelques notions que je n'ai pas.
    Dans les cours que j'ai lus ce point particulier n'est j'amais détaillé, donc pouvez vous m'expliquer le principe ?

    On inclus pas de .cpp, donc dans main.cpp on inclus par exemple fonctions.h et dans fonctions.h on inclus fonctions.cpp ?

    Mais, c'est plutôt une règle que tout le monde se fixe, je ne pense pas que ça influs sur quelque chose à la compilation, exacte ?
    Dans mon cas, j'inclus fonctions.cpp avant WinMain, donc pas besoin de déclarer mes fonctions, donc pas théoriquement pas besoin de .h, même si apparament c'est comme ça que ça se fait, exacte ?

    Sinon, pour l'extension .c ou .cpp, le compilateur choisis entre compiler en C ou en C++ seulement en fonction de l'extension ?

    Pour diagnostiquer mon problème de définition mutliple, vous voulez le code source entier ?

    Merci beaucoup.
    Pierre.

  8. #8
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par Pierre.g
    Je savais bien qu'au niveau des inclusion il y a quelques notions que je n'ai pas.
    Dans les cours que j'ai lus ce point particulier n'est j'amais détaillé, donc pouvez vous m'expliquer le principe ?
    http://emmanuel-delahaye.developpez.com/codage.htm
    http://emmanuel-delahaye.developpez....htm#production
    On inclus pas de .cpp, donc dans main.cpp on inclus par exemple fonctions.h et dans fonctions.h on inclus fonctions.cpp ?
    Non. La Bonne Pratique est expliquée au-dessus. Pose des question si tu ne comprends pas.
    Mais, c'est plutôt une règle que tout le monde se fixe, je ne pense pas que ça influs sur quelque chose à la compilation, exacte ?
    La compilation, on, l'édition de lien, si. La preuve.
    Dans mon cas, j'inclus fonctions.cpp avant WinMain, donc pas besoin de déclarer mes fonctions, donc pas théoriquement pas besoin de .h, même si apparament c'est comme ça que ça se fait, exacte ?
    Il faut renoncer définitivement à cette idée d'inclure du source dans du source. C'est une mauvaise pratique qui ne même qu'a des problèmes. La Bonne Pratique est issue de l'expérience et elle est universellement appliquée avec succès.
    Sinon, pour l'extension .c ou .cpp, le compilateur choisis entre compiler en C ou en C++ seulement en fonction de l'extension ?
    Le plus souvent, oui.
    Pour diagnostiquer mon problème de définition mutliple, vous voulez le code source entier ?
    Non. Si tu te contentes de suivre les regles de bon usage du C, ça devrait aller. Entraine toi sur un mini projet à 3 fichers comme dans l'exemple du lien que je t'ai passé.

    Apprend à bien utiliser ton environnement de développement pour gérer un projet multisources.
    Pas de Wi-Fi à la maison : CPL

  9. #9
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 626
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 626
    Points : 30 684
    Points
    30 684
    Par défaut
    Salut,

    Pour que tu puisse comprendre un tout petit peu, il faut savoir que la création de l'exécutable se fait en trois étapes distinctes (le "preprocessing", la compilation et l'édition des lien) et que les trois outils utilisés sont, d'une certaine manière "bête à bouffer du foin" (meme s'il sont très fiables et qu'ils n'ont pas été, loin de là, écrits par des manchots)...

    Le préprocesseur, qui est l'outil utilisé dans la première étape va "se contenter"(et c'est déjà pas si mal) de recopier certaines choses à la place d'autres choses... exemple
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    #define mondef "bonjour"
    fera que, partout où le preprocesseur vera mondef, il le remplacera par "bonjour"
    fera qu'il recopieras le contenu du fichier "fichier.h" à la place de l'instruction elle-meme

    Le compilateur prendra chaque fichier qui contient du code et le transformera en instructions binaires, compréhensible par le processeur (il créera un fichier "objet" pour chaque fichier qui contient du code)

    L'éditeur de lien, enfin, fera correspondre l'appel d'une fonction avec l'adresse mémoire à laquelle se trouve effectivement la fonction (en reliant les différents fichiers objets)

    Je laisse volontairement des détails, et meme certaines erreurs, sur le coté le but étant de donner une vue d'ensemble

    Si le préprocesseur ne pose pas (trop) de problème, le compilateur fournit déjà un travail beaucoup plus complexe...

    Or, il se fait qu'il ne connait... que ce qu'il a déjà rencontré...

    Arrivé à la ligne 100 du fichier qu'il traite (modifié par le préprocesseur) il ne connait que ce qui se trouve dans les lignes 1 à 99...(qui est peut etre le contenu d'un fichier inclu pour ce qui concerne les lignes 1 à 40)... mais il ne sait strictement rien de ce qui se trouve à la ligne 101 (ou peu s'en faut)

    S'il a rencontré des déclarations (des prototypes) de fonctions dans les lignes qu'il a déjà parcourrues, il saura que les fonctions existent, et préparera le travail de l'éditeur de lien en conséquence, en créant une liste d'équivalence "fonctiona() se trouve à tel endroit, fonctionb() à tel endroit..." pour chaque fichier objet qu'il crée.

    Seulement, une fois qu'il a fini de créer un fichier objet, il oublie ce qu'il a fait pour ce fichier... et il passe au suivant.

    Si, pas de bol, le préprocesseur a recopié la définition d'une fonction dans le fichier suivant, le compilateur créera le code binaire correspondant, et rajoutera la fonction dans la liste des fonctions qu'il a créées...

    Enfin, l'éditeur de liens commencera par lire la liste des fonctions de tous les fichiers objets...

    S'il trouve dans l'un d'eux l'adresse d'une fonction pour laquelle il a déjà une adresse, il ne saura pas déterminer... quelle est l'adresse à utiliser...Et il t'enverra alors une erreur "fonction déjà définie"

    C'est comme toi, à un carrefour où tu peux aller à gauche ou à droite, si je te dit "tourne", tu me demandras "par où?"

    Par contre, si, en fin de compte, il se rend compte qu'on a défini une fonction, que, quelque part, on y fait appel, mais qu'on a jamais dit ce qu'elle devait faire (donc qu'il n'y a pas d'adresse correspondante pour la fonction), il ne saura pas non plus travailler, et t'enverra un message de "référence à une fonction indéfinie"...

    C'est la raison pour laquelle, quand on travaille sur plusieurs fichiers (car, rien ne t'empeche de tout mettre dans un meme fichier... hormis le fait que ca te complique la vie dés que le projet devient un tout petit peu important), ce qui importe, c'est que le compilateur connaisse les fonctions (qu'il ai les prototypes).

    Les prototypes sont mis, dans dest fichiers qu'en appelle "entete" et qui prennent, par convention (est-ce une convention, ou est-ce la norme??) l'extention .h (pour Header)

    Les définitions des fonction(la suite d'instruction qu'elle doivent suivre), par contre, prend place dans le fichier de code source qui par convention (ou par norme), prennent l'extention .c (pour dire que ce n'est pas du java )

    Si tu as compris ces explications, tu comprendra que, ce qu'il faut, c'est inclure les fichiers d'entetes, qui contiennent les déclarations (les prototypes) des fonctions
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  10. #10
    Membre régulier
    Profil pro
    Inscrit en
    Août 2006
    Messages
    256
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 256
    Points : 91
    Points
    91
    Par défaut
    Merci koala01 pour avoir pris pas mal de temps pour ton explication, et merci Emmanuel pour ton site.

    Maintenant j'ai compris mon erreur, je croyais que quand l'on rajoutais un fichier au projet il n'étais pas compilé, enfin je ne m'étais pas trop attardé dessus parce que j'ai un peut l'habitude du php ou si l'on inclus rien dans un fichier ... rien d'autre n'est pris en compte auromatiquement.

    Par contre, maintenant je me pose une autre question, puisque le compilateur génère des fichiers objets et qu'ils sont rassemblés après, ça ne fait pas baisser un poil les performances, ça ne fais pas faire un micro-poil plus bosser le prosseur ? Ou alors ça reviens exactement au même au finale que de tout mettre dans un seul fichier ?

    Merci.
    A+, Pierre.

  11. #11
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 626
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 626
    Points : 30 684
    Points
    30 684
    Par défaut
    Absolument pas...

    En fait, j'ai peut etre manqué un peu de précision...

    L'éditeur de lien va rassembler l'ensemble des fichiers objet dans un seul fichier "final" qui sera l'exécutable.

    un parallele peut etre un peu osé pourrait etre que le compilateur est l'ensemble des usines qui font les pièces détachées d'une voiture et l'éditeur de lien, l'usine d'assemblage de toutes ces pièces de manière à ce que tout se trouve à sa place...

    Il faut savoir que, au niveau du processeur, il existe une instruction "call" qui permet d'appeler une "sous routine" avant de reprendre l'exéctution du reste là ou elle a été quitée...

    Du fait qu'il s'agit principalement d'appeler une adresse mémoire donnée (apres avoir effectué quelques actions qui sortent du cadre de cet exposé), et que, qu'il s'agisse de "sauter" de 150 cases mémoire, ou de 500, cela ne prend absolument ni plus ni moins de temps...

    Quand tu as ta voiture, ses caractéristiques sont propres et n'ont rien à voir avec l'endroit où les pièces ont été fabriquées

    Les différences apparaitront par la manière dont les pieces détachées ont été concues...Mais qu'une piece ai été fabriquée en hollande ou autre en chine ne changera rien
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  12. #12
    Membre régulier
    Profil pro
    Inscrit en
    Août 2006
    Messages
    256
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 256
    Points : 91
    Points
    91
    Par défaut
    Ok, merci bien koala01, je comprend maintenant mieux comment bosse tout ça, je ne devrais plus faire le genre d'erreur de tout à l'heure.

    A+, Pierre.

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

Discussions similaires

  1. Réponses: 1
    Dernier message: 11/12/2013, 22h17
  2. [XL-2007] Problème avec la fonction Split et un tableau
    Par flo1411 dans le forum Macros et VBA Excel
    Réponses: 16
    Dernier message: 15/04/2013, 09h56
  3. problème avec une fonction qui affiche une page blanche
    Par piotrowski-s dans le forum Langage
    Réponses: 3
    Dernier message: 16/11/2012, 18h25
  4. [GD] Problème avec des fonctions qui créent des éléments dans une image.
    Par magnus2229 dans le forum Bibliothèques et frameworks
    Réponses: 2
    Dernier message: 13/07/2011, 09h38
  5. Problème avec une fonction qui supprime un dossier
    Par Mo_Poly dans le forum Langage
    Réponses: 3
    Dernier message: 18/03/2008, 18h39

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