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 :

Déclaration de référence pour un tableau dans un header


Sujet :

C

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Avril 2010
    Messages
    124
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Avril 2010
    Messages : 124
    Points : 52
    Points
    52
    Par défaut Déclaration de référence pour un tableau dans un header
    Bonjour,

    Dans le code que j'utilise, j'ai plusieurs variables globales, dont un tableaux de type int TAB[2][n].

    Définis dans l'un des fichiers file1.c, j'aimerais m'en servir dans un autre fichier file2.c.
    J'ai donc créé un fichier Entete.h destiné à être inclus dans file2.c.

    Quelle forme aura ma déclaration de référence dans Entente.h ?
    Celle-ci ne semble pas convenir au compilateur :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    extern int TAB[2][n];
    Faut il passer par le pointeur comme ceci ?

    Merci de votre aide.

  2. #2
    Invité
    Invité(e)
    Par défaut
    C'est normal que cela ne lui plaise pas. Et il râle à juste raison !

    Tu lui dis qu'il existe quelque part une variable, qui est un tableau de taille variable.
    Comment tu veux que, pauvre petit compilateur qu'il est, puisse savoir qu'elle sera la taille de ce tableau, et jusque dans quel mesure il pourra l'utiliser ?

    Le soucis avec ton tableau à taille dynamique, là, c'est que tu ne pourras le lui faire avaler.

    Soit tu lui donnes une adresse fixe, soit tu es dans l'obligation d'utiliser un pointeur. L'avantage du pointeur est qu'il te permet justement de masquer cette partie dynamique.
    Par contre, il faut du coup faire beaucoup plus attention dans son utilisation. C'est moins "parlant" qu'un tableau.

    Je dirais que d'une manière générale, essaye d'éviter ce style d'écriture, même si cela fait partie de la norme C99. Cela amène beaucoup d'embrouille pour un avantage somme-toute assez réduit (je trouve, personnellement).

    Quand à la manière de présenter la chose...

    Si tu es courageux: extern int *montableau Mais tu devras alors gérer manuellement chaque niveau de ton tableau.
    Sinon, pour paraphraser ce que j'ai pu lire ici : "Une étoile par dimension supplémentaire" pour un tableau, donc extern int **montableau dans ton cas. (mais je m'attends à ce que l'on me reprenne sur cette affirmation.)

  3. #3
    Expert éminent sénior
    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
    Points : 13 926
    Points
    13 926
    Par défaut
    Citation Envoyé par archMqx. Voir le message
    ...
    Soit tu lui donnes une adresse fixe, soit tu es dans l'obligation d'utiliser un pointeur. L'avantage du pointeur est qu'il te permet justement de masquer cette partie dynamique.
    Par contre, il faut du coup faire beaucoup plus attention dans son utilisation. C'est moins "parlant" qu'un tableau.
    Ce n'est pas moins parlant, c'est autre chose.

    Citation Envoyé par archMqx. Voir le message
    ...
    Je dirais que d'une manière générale, essaye d'éviter ce style d'écriture, même si cela fait partie de la norme C99. Cela amène beaucoup d'embrouille pour un avantage somme-toute assez réduit (je trouve, personnellement).
    A quelle particularité de la C99 fais-tu allusion? aux VLA ?

    Citation Envoyé par archMqx. Voir le message
    ...
    Si tu es courageux: extern int *montableau Mais tu devras alors gérer manuellement chaque niveau de ton tableau.
    Sinon, pour paraphraser ce que j'ai pu lire ici : "Une étoile par dimension supplémentaire" pour un tableau, donc extern int **montableau dans ton cas. (mais je m'attends à ce que l'on me reprenne sur cette affirmation.)
    Et tu ne te trompes pas : il n'y a aucun rapport entre le nombre de dimensions et d'étoiles. C'est une faute de dire ceci, même avec l'intention de faire simple, car cette affirmation est fondamentalement fausse et induit une incompréhension totale des tableaux en C.

    D'un autre coté, je ne suis pas sûr qu'on puisse avoir une déclaration extern qui ne soit pas strictement identique à celle de la variable.

    De toute façon, int TAB[2][n] ne peut pas être en allocation statique mais doit être en allocation automatique (variable locale) et ne peut donc figurer en extern. Il faut revoir la conception des structures de données.

  4. #4
    Membre du Club
    Profil pro
    Inscrit en
    Avril 2010
    Messages
    124
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Avril 2010
    Messages : 124
    Points : 52
    Points
    52
    Par défaut
    Bonjour et avant tout, un grand merci de vos réponses !

    Par rapport à celles-ci, il me reste encore quelques points problèmatiques:

    * Tout d'abord la taille de TAB n'est pas variable puisque n ne change pas dans le programme. Mais j'imagine que pour la déclaration de référence, le fait que n varie ou pas dans le reste du code ne change rien à la confusion de cette écriture pour le compilateur.

    *
    Si tu es courageux: extern int *montableau Mais tu devras alors gérer manuellement chaque niveau de ton tableau
    Que signifie "gérer manuellement chaque niveau de mon tableau" ?

    *
    Je dirais que d'une manière générale, essaye d'éviter ce style d'écriture, même si cela fait partie de la norme C99. Cela amène beaucoup d'embrouille pour un avantage somme-toute assez réduit (je trouve, personnellement).
    Je ne comprend pas de quel style d'écriture tu parles. Parles tu de l'écriture 'extern' dans les headers ? De la déclaration de référence avec un pointeur ?

    * D'après ce que j'ai maintenant compris, je vais déclarer TAB dans le header en passant par son adresse :extern int* TAB
    Si cela ne passe du fait que la déclaration extern n'est pas strictement identique à celle de la variable, je pensais donc changer la déclaration-définition de TAB et en faire un pointeur.
    Par exemple dans le main :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    int** TAB;
    TAB= (int**) malloc(2 * sizeof(int*));
    for (i = 0; i < 2; i++)
            TAB[i] = (int*) malloc(n * sizeof(int));
    et dans le header :

    Est-ce que cela équivalent à l'usage d'un tableau ? (Je ne suis pas encore sûre de moi sur les pointeur et allocations de mémoire)

    * dernière chose sur le principe : j'ai lu qu'il n'était pas recommandé d'utiliser beaucoup de variables globales. Mais il est également déconseillé d'avoir d'énormes liste d'argument à
    l'entrée des fonctions.... Comment faire alors ??

    Merci encore à vous

  5. #5
    Membre du Club
    Profil pro
    Inscrit en
    Avril 2010
    Messages
    124
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Avril 2010
    Messages : 124
    Points : 52
    Points
    52
    Par défaut
    Je viens d'avoir une idée, comme ma variable n ne varie pas de tout le programme, je peux en faire une macro et définir dans le header :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    #define N 100
    extern int TAB[2][N];

    Qu'en pensez vous ?

  6. #6
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 195
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 195
    Points : 17 163
    Points
    17 163
    Par défaut
    Que ca change tout.

    Une macro est remplacé par son "texte de remplacement" à la précompilation.

    Ce qui sera effectivement compilé est extern int TAB[2][100];. Et là, tu as bien un tableau de taille connue à la compilation.

  7. #7
    Membre du Club
    Profil pro
    Inscrit en
    Avril 2010
    Messages
    124
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Avril 2010
    Messages : 124
    Points : 52
    Points
    52
    Par défaut
    et comment faire pour que mes macros soient incluses dans tous les fichiers header nécessaires ? Les définir dans un autre header qui sera inclus dans file1.h, file2.h ?

    Merci,

  8. #8
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 195
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 195
    Points : 17 163
    Points
    17 163
    Par défaut
    non, dans le seul en-tête qui déclare le tableau.

  9. #9
    Membre du Club
    Profil pro
    Inscrit en
    Avril 2010
    Messages
    124
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Avril 2010
    Messages : 124
    Points : 52
    Points
    52
    Par défaut
    En fait, comme file1.c et file2.c utilisent TAB, je dois faire une déclaration de référence avec "extern" dans file.h et file2.h.
    Les macros doivent être connues dans ces deux fichiers.
    Mais il est redondant de les définir au début de file1.h et file2.h non?

    Merci

  10. #10
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 195
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 195
    Points : 17 163
    Points
    17 163
    Par défaut
    tu peux surtout avoir un tab.h (ou autre nom) qui s'occupe de déclarer tab et les fonctions qui vont avec, et l'inclure dans file1.c et file2.c

    Ca revient au même pour la compilation (il y aura un extern tab dans les deux unités de compilation), mais pas pour le code source, vu que tu ne l'auras écris qu'une fois.

    Et si demain tu as besoin de tab dans un file3.c, tu n'auras pas à redéclarer tab, mais juste à inclure le .h

  11. #11
    Membre du Club
    Profil pro
    Inscrit en
    Avril 2010
    Messages
    124
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Avril 2010
    Messages : 124
    Points : 52
    Points
    52
    Par défaut
    Oui, mais par contre, je vais inclure toutes les variables déclarées avec extern dans les deux fichiers, alors que certaines n'y seront pas utiles. Ne sachant pas comment faire, j'avais l'impression que c'était plus pertinent de faire un seul header par fichier .c, qui soit totalement adapté à ce fichier....
    N'est ce pas le cas?

  12. #12
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 195
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 195
    Points : 17 163
    Points
    17 163
    Par défaut
    C'est dans l'autre sens qu'il faut penser.

    Tu définis des en-têtes qui ont un rôle, puis tu implémentes toutes les déclarations dans des .c.

    En général, par un fichier par en-tête, mais ce n'est pas obligatoire.
    Tu peux parfois avoir un .c pour deux .h, si par exemple tu as des détails d'implémentation à partager entre les deux (même si je ferai un .h supplémentaire dans ce cas)

    Et tu peux plus facilement rencontrer deux .c pour un seul .h


    L'idée principale, c'est de privilégier le sens à la forme.
    Ton tableau fait partie d'une idée, c'est autour d'elle que doit se construire l'en-tête qui le définit.


    D'ailleurs, ça ne te gène absoluement pas d'inclure stdio.h et stdlib.h, alors même que tu n'as pas besoin de tous les morceaux qu'ils déclarent.

  13. #13
    Membre du Club
    Profil pro
    Inscrit en
    Avril 2010
    Messages
    124
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Avril 2010
    Messages : 124
    Points : 52
    Points
    52
    Par défaut
    Tout d'abord, merci beaucoup de votre réponse.

    Du coup je vois mal comment organiser les déclarations de référence des variables globales (avec "extern" donc).

    En considérant par exemple un code avec :
    main.c
    file1.h inclut dans file1.c
    file2.h inclut dans file2.c
    (les headers contenant déjà les prototype des fonctions définies dans les fichiers .c associées)

    Les variables étant 'globales', elles servent dans tous les fichiers .c !
    Un seul header avec toutes les variables globales en "extern" (à inclure dans tous les fichiers .c) est-il une bonne solution à intégrer ?

  14. #14
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 483
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    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 483
    Points : 13 685
    Points
    13 685
    Billets dans le blog
    1
    Par défaut
    Je me souviens d'une erreur que je faisais étant débutant et j'ai l'impression que tu fais la même. Cette erreur est l'idée de penser que pour chaque .c, on crée un .h où on ajoute plein de #include, de définitions externes et autres typedefs, et que ce .h est le seul à être inclus dans le .c.

    C'est dans l'autre sens qu'il faut penser.
    Et c'est bien de ça dont il s'agit : un .h associé à un .c est au contraire fait pour être inclus dans les autres .c qui ont besoin d'accéder au contenu du .c que ce fichier .h accompagne.
    • Exemple : si tu as un tableau dans un.c et que tu en as besoin dans deux.c, alors tu fais un.h avec la déclaration externe du tableau et tu l'inclus dans deux.c.
    • Autre exemple : si tu as besoin d'un type dans un.c et uniquement à l'intérieur de un.c, alors le typedef n'est pas dans un.h mais dans un.c. En effet, deux.c n'a pas besoin de le connaitre.

  15. #15
    Membre du Club
    Profil pro
    Inscrit en
    Avril 2010
    Messages
    124
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Avril 2010
    Messages : 124
    Points : 52
    Points
    52
    Par défaut
    Cela s'éclaircit donc pour moi. Avec cette approche on va donc inclure possiblement des déclarations extern de variables des des fichiers .c qui n'y sont pas utilisées (car le .h comprend plusiers déclarations externes), mais ce n'est pas grave.
    Créer un header global avec toutes les déclarations extern des variables globales, est ce une bonne idée ?

    Merci à vous

  16. #16
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 483
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    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 483
    Points : 13 685
    Points
    13 685
    Billets dans le blog
    1
    Par défaut
    Je t'ai déjà donné mon avis dans une autre discussion à ce sujet. Mon avis n'a pas changé

  17. #17
    Membre du Club
    Profil pro
    Inscrit en
    Avril 2010
    Messages
    124
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Avril 2010
    Messages : 124
    Points : 52
    Points
    52
    Par défaut
    Oui, je viens de relire. Il me semblait que tu parlais du regroupement des variables globales dans les fichiers .c et pas des fichiers .h, mais si...

    Le problème qui se pose à moi est comment placer de manière logique les déclarations des "extern" dans les headers ? Car pour moi, la plupart des variables globales (que je déclare/définis dans le main.c) sont utilisées dans presque tous les fichiers ...
    Si vous avez des conseils, je suis preneuse.

  18. #18
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 195
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 195
    Points : 17 163
    Points
    17 163
    Par défaut
    Le mieux, c'est de diviser tes déclarations en unités logiques.

    Supposons qu'on parle de mathématiques.
    Le calcul d'une factorielle n'a rien à voir (a priori) avec le parcours d'un graphe, et aucun des deux avec la translation d'un triangle ou la définition d'un repère. Il n'y a aucune raison de les regrouper.
    Si j'ai besoin de la factorielle dans l'implémentation d'une fonction sur les graphes, il suffira d'inclure la factorielle dans le .c contenant cette fonction.

    Par exemple, en premier découpage, je ferai bien ceci:
    • arithmétique
    • géométrie
    • analyse fonctionnelle
    • graphes


    Une fois cela fait, tu peux aussi avoir une unité pour les quelques grandes constantes comme pi et e. et inclure cet en-tête dans arith.h et geom.h.

    A toi de voir comment découper l'interface de ton code.
    Imagine que tu veuilles donner ton code comme une bibliothèque, ne mets dans les en-têtes que ce qui doit être vu par le développeur qui utilisera le code.
    Si d'autres choses ont besoin d'être déclarées localement pour l'implémentation, déclare les uniquement dans le .c.

  19. #19
    Membre du Club
    Profil pro
    Inscrit en
    Avril 2010
    Messages
    124
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Avril 2010
    Messages : 124
    Points : 52
    Points
    52
    Par défaut
    Entendu,

    Je vais y réfléchir,

    Merci de votre aide précieuse à tous !

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

Discussions similaires

  1. [XL-2010] Formule matricielle pour filtrer tableau dans Plage Nommée
    Par Gpadidee dans le forum Excel
    Réponses: 1
    Dernier message: 28/02/2014, 01h05
  2. Réponses: 4
    Dernier message: 27/08/2013, 20h10
  3. CSS pour un tableau dans du XHTML
    Par darkterreur dans le forum Mise en page CSS
    Réponses: 16
    Dernier message: 18/06/2010, 10h20
  4. Tableau dans un header
    Par ancrou dans le forum C++
    Réponses: 14
    Dernier message: 10/07/2008, 21h20
  5. Réponses: 1
    Dernier message: 23/09/2006, 00h41

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