132 votes

Comment déclarer une structure dans un en-tête qui doit être utilisée par plusieurs fichiers en c ?

Si j'ai un fichier source.c avec une structure :

struct a
{ 
    int i;
    struct b
    {
        int j;
    }
};

Comment cette structure peut-elle être utilisée dans un autre fichier (par ex. func.c ) ?

Devrais-je créer un nouveau fichier d'en-tête, y déclarer la structure et inclure cet en-tête dans func.c ?

Ou dois-je définir la structure entière dans un fichier d'en-tête et l'inclure dans les deux fichiers source.c y func.c ? Comment déclarer la structure extern dans les deux fichiers ?

Devrais-je typedef elle ? Si oui, comment ?

158voto

paercebal Points 38526

si cette structure doit être utilisée par un autre fichier func.c, comment faire ?

Lorsqu'un type est utilisé dans un fichier (par exemple le fichier func.c), il doit être visible. La pire façon de le faire est de le copier-coller dans chaque fichier source qui en a besoin.

Le bon moyen est de le mettre dans un fichier d'en-tête, et d'inclure ce fichier d'en-tête chaque fois que cela est nécessaire.

devons-nous ouvrir un nouveau fichier d'en-tête, y déclarer la structure et inclure cet en-tête dans le fichier func.c ?

C'est la solution que je préfère, car elle rend le code très modulaire. Je coderais votre struct comme :

#ifndef SOME_HEADER_GUARD_WITH_UNIQUE_NAME
#define SOME_HEADER_GUARD_WITH_UNIQUE_NAME

struct a
{ 
    int i;
    struct b
    {
        int j;
    }
};

#endif

Je mettrais les fonctions utilisant cette structure dans le même en-tête (la fonction qui fait "sémantiquement" partie de son "interface").

Et généralement, je pouvais nommer le fichier après le nom de la structure, et utiliser à nouveau ce nom pour choisir les gardes d'en-tête définis.

Si vous devez déclarer une fonction en utilisant un pointeur vers la structure, vous n'aurez pas besoin de la définition complète de la structure. Une simple déclaration en avant comme :

struct a ;

Sera suffisant, et il diminue l'accouplement.

ou pouvons-nous définir la structure totale dans le fichier d'en-tête et l'inclure à la fois dans source.c et func.c ?

C'est un autre moyen, plus facile en quelque sorte, mais moins modulaire : Un code n'ayant besoin que de votre structure pour fonctionner devrait quand même inclure tous les types.

En C++, cela pourrait conduire à une complication intéressante, mais c'est hors sujet (pas de balise C++), donc je ne m'étendrai pas.

alors comment déclarer cette structure comme externe dans les deux fichiers. ?

Je ne vois pas l'intérêt, peut-être, mais Greg Hewgill a une très bonne réponse dans son article. http://stackoverflow.com/questions/228684/how-to-declare-a-structure-in-a-header-that-is-to-be-used-by-multiple-files-in-c#228691 .

Comment le définir alors ?

  • Si vous utilisez C++, ne le faites pas.
  • Si vous utilisez le C, vous devriez.

La raison en est que la gestion des structures C peut être pénible : Vous devez déclarer le mot-clé struct partout où il est utilisé :

struct MyStruct ; /* Forward declaration */

struct MyStruct
{
   /* etc. */
} ;

void doSomething(struct MyStruct * p) /* parameter */
{
   struct MyStruct a ; /* variable */
   /* etc */
}

Alors qu'un typedef vous permettra de l'écrire sans le mot clé struct.

struct MyStructTag ; /* Forward declaration */

typedef struct MyStructTag
{
   /* etc. */
} MyStruct ;

void doSomething(MyStruct * p) /* parameter */
{
   MyStruct a ; /* variable */
   /* etc */
}

Il est important vous gardez toujours un nom pour la structure. L'écriture :

typedef struct
{
   /* etc. */
} MyStruct ;

créera simplement une structure anonyme avec un nom typé, et vous ne serez pas en mesure de la déclarer à nouveau. Respectez donc le format suivant :

typedef struct MyStructTag
{
   /* etc. */
} MyStruct ;

Ainsi, vous pourrez utiliser MyStruct partout où vous voulez éviter d'ajouter le mot-clé struct, et toujours utiliser MyStructTag lorsqu'un typedef ne fonctionnera pas (c'est-à-dire une déclaration en avant).

Edit :

Correction d'une hypothèse erronée concernant la déclaration C99 struct, comme l'a remarqué Jonathan Leffler.

40voto

Greg Hewgill Points 356191

Pour une définition de structure qui doit être utilisée dans plus d'un fichier source, vous devez absolument la placer dans un fichier d'en-tête. Ensuite, incluez ce fichier d'en-tête dans tout fichier source qui a besoin de la structure.

El extern n'est pas utilisée pour les définitions de structure, mais plutôt pour les déclarations de variables (c'est-à-dire des valeurs de données avec un type de structure que vous avez défini). Si vous souhaitez utiliser la même variable dans plusieurs fichiers sources, déclarez-la comme suit extern dans un fichier d'en-tête comme :

extern struct a myAValue;

Ensuite, en un le fichier source, définissez la variable réelle :

struct a myAValue;

Si vous oubliez de le faire ou si vous le définissez accidentellement dans deux fichiers sources, l'éditeur de liens vous le fera savoir.

7voto

fmsf Points 13399

A.h :

#ifndef A_H
#define A_H

struct a
{ 
    int i;
    struct b
    {
        int j;
    }
};

#endif

Voilà, maintenant vous n'avez plus qu'à inclure a.h dans les fichiers où vous voulez utiliser cette structure.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X