si cette structure doit être utilisée par un autre fichier func.c comment faire?
Lorsqu'un type est utilisé dans un fichier (ie fichier func.c), il doit être visible. Le pire moyen de le faire est de le copier-coller dans chaque fichier source dont il a besoin.
La bonne façon est de le mettre dans un fichier d'en-tête et d'inclure ce fichier d'en-tête chaque fois que nécessaire.
devons-nous ouvrir un nouveau fichier d'en-tête et y déclarer la structure et inclure cet en-tête dans func.c?
C'est la solution que j'aime le plus, car elle rend le code très modulaire. Je coderais votre structure 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 pourrais 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 à l'aide d'un pointeur vers la structure, vous n'aurez pas besoin de la définition complète de la structure. Une simple déclaration avant comme:
struct a ;
Sera suffisant, et cela diminue le couplage.
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 une autre façon, un peu plus simple, mais moins modulaire: certains codes n'ayant besoin que de votre structure pour fonctionner devraient 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 vais pas élaborer.
puis comment déclarer cette structure comme extern dans les deux fichiers. ?
Je ne vois pas le point, peut-être, mais Greg Hewgill a une très bonne réponse dans son article Comment déclarer une structure dans un en-tête qui doit être utilisée par plusieurs fichiers en c? .
devons-nous le taper alors comment?
- Si vous utilisez C ++, ne le faites pas.
- Si vous utilisez 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 que vous conserviez un nom pour la structure. L'écriture:
typedef struct
{
/* etc. */
} MyStruct ;
créera simplement une structure anonyme avec un nom typé, et vous ne pourrez pas la déclarer en avant. Alors gardez 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 quand un typedef ne fonctionnera pas (ie déclaration forward)
Éditer:
Correction de l'hypothèse erronée concernant la déclaration de struct C99, comme l'a remarqué à juste titre Jonathan Leffler .
Modifier le 01/06/2018:
Craig Barnes nous rappelle dans son commentaire que vous n'avez pas besoin de garder des noms séparés pour le nom de la structure "tag" et son nom "typedef", comme je l'ai fait ci-dessus par souci de clarté.
En effet, le code ci-dessus pourrait bien s'écrire comme:
typedef struct MyStruct
{
/* etc. */
} MyStruct ;
IIRC, c'est en fait ce que fait C ++ avec sa déclaration struct plus simple, dans les coulisses, pour le garder compatible avec C:
// C++ explicit declaration by the user
struct MyStruct
{
/* etc. */
} ;
// C++ standard then implicitly adds the following line
typedef MyStruct MyStruct;
De retour en C, j'ai vu les deux usages (noms séparés et mêmes noms), et aucun n'a d'inconvénients que je connaisse, donc utiliser le même nom rend la lecture plus simple si vous n'utilisez pas des "espaces de noms" séparés en C pour les structures et autres symboles .
struct b
, mais votre structurea
déclare un type qui n'est pas utilisé (vous devriez probablement définir un nom de membre, peutk
- être , après l'accolade de fermeture interne et avant le point-virgule.