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 (ie func.c
)?
Dois-je créer un nouveau fichier d'en-tête, y déclarer la structure et inclure cet en-tête func.c
?
Ou devrais-je définir la structure entière dans un fichier d'en-tête et l'inclure dans les deux source.c
et func.c
? Comment la structure peut-elle être déclarée extern
dans les deux fichiers?
Dois-je le typedef
faire? Si c'est le cas, comment?
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.Réponses:
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:
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:
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?
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é:
Alors qu'un typedef vous permettra de l'écrire sans le mot clé struct.
Il est important que vous conserviez un nom pour la structure. L'écriture:
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:
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:
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:
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 .
la source
struct
balise et letypedef
nom. C utilise un espace de noms différent pour lesstruct
balises, vous pouvez donc l'utiliserMyStruct
pour les deux.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. Incluez ensuite ce fichier d'en-tête dans tout fichier source qui a besoin de la structure.
La
extern
déclaration n'est pas utilisée pour les définitions de structure, mais est plutôt utilisée pour les déclarations de variables (c'est-à-dire, une valeur de données avec un type de structure que vous avez défini). Si vous souhaitez utiliser la même variable dans plus d'un fichier source, déclarez-la commeextern
dans un fichier d'en-tête comme:Ensuite, dans un fichier source, définissez la variable réelle:
Si vous oubliez de le faire ou le définissez accidentellement dans deux fichiers source, l'éditeur de liens vous en informera.
la source
GLOBAL
commeextern
ou rien en haut de l'en-tête, puis à déclarer les variables commeGLOBAL struct a myAValue;
. À partir de la plupart des fichiers source, vous organisez la#define GLOBAL extern
version à utiliser (en déclarant les variables) et à partir d'exactement un fichier source, vous utilisez la définition vide pour que les variables soient définies .ah:
là vous allez, il vous suffit maintenant d'inclure ah dans les fichiers où vous souhaitez utiliser cette structure.
la source