2016-03-15 1 views
0

J'ai un léger problème avec mes fichiers d'inclusion et j'ai fait une maquette simplifiée de mon problème. dire que je suis la compilation d'une source qui nécessite un fichier d'en-tête nomméTransférer "Typedefing" une structure

header.h 

Ce qui a en elle:

#ifndef HEADER_INCLUDED 
#define HEADER_INCLUDED 

#include element.h 
typedef struct { 
    Element *list; 
} Thing; 

#endif 

, j'ai un autre fichier d'en-tête définissant cet élément et nécessitant également header.h. J'ai ensuite rencontré un problème car element.h ne peut pas savoir quel est le type de chose; nous n'avons pas atteint cette définition dans header.h car nous devions inclure element.h.

Je pensais que je pourrais peut-être résoudre mon problème pour « typedefing avant » un type de chose à element.h et juste avant le prototype void * func comme

typedef struct thing Thing; 

Alors ce juste crée un autre problème et le compilateur se plaint qu'il existe des types contradictoires pour Thing.

Comment sortir de ce bordel?

+0

'typedef struct Elément;' est invalide. Voulez-vous dire «typedef struct Element Element»? Quelle est la plainte du compilateur au sujet de «Thing»? – Potatoswatter

+0

@Potatoswatter en fait il est valide et cela signifie la même chose que 'struct Element; –

Répondre

0

La manière la plus simple de résoudre votre problème est d'isoler votre définition de structure dans son propre en-tête, protégé par # ifndef/# define comme d'habitude. Si vous ne voulez pas un fichier d'en-tête de cette structure unique, définir la struct deux fois et protéger sa définition par un autre # ifndef/# définir ainsi:

#ifndef __BOOLEAN_ENUM__ 
#define __BOOLEAN_ENUM__ 
enum boolean 
{ 
    false = 0, 
    true = 1 
}; 
#endif 
1

Votre principal problème est qu'il ya une dépendance cyclique entre le 2, mais vous utilisez des macros de garde. Les fichiers sont inclus presque comme s'ils étaient copiés-collés - l'un des fichiers doit être inclus avant l'autre, donc vous ne pouvez pas avoir une telle dépendance cyclique. Repensez votre structure. Déclarer/définir le type de données de base à 1 place, puis les types de données dérivés/composites en utilisant cela, et enfin les fonctions qui prennent ces types comme arguments/valeurs de retour.

En outre, typedef struct Element; est invalide typedef.

0

header.h ne doit pas inclure element.h. Sinon, vous avez une dépendance circulaire.

Le code que vous avez publié comporte un grand nombre d'erreurs. (À l'avenir, publiez du vrai code que vous avez essayé de compiler, au lieu de faire des choses au fur et à mesure dans la boîte d'édition). Voici un exemple, où j'ai omis les gardiens d'en-tête pour la brièveté:

// header.h 
struct Element;  // actually not necessary, but may help with readability 

typedef struct 
{ 
    struct Element *ptr; 
} Thing; 

et

// element.h 
#include "header.h" 

struct Element 
{ 
    int x; 
}; 

typedef struct Element Element; // optional 

void * func(Thing *myThing); 

Il serait possible de placer également typedef struct Element Element; dans header.h et utiliser Element *ptr dans la définition de Thing, il est une question de goût quant à la façon dont vous préférez. Certaines personnes désapprouvent l'utilisation de typedef avec des structs du tout en C, cependant je l'aime car cela signifie qu'une faute de frappe mène à une erreur de compilation immédiate, au lieu de créer silencieusement un nouveau type.

Si vous souhaitez également que element.h ne dépende pas de header.h, vous pouvez utiliser la même technique avec Thing. Vous devez lui donner une balise struct, comme struct Element.

0

Faites simplement un pas en arrière par rapport au code C et à la conception globale du programme.

Il est clair que la structure "Thing" doit dépendre de la structure "Element" dans element.h. Cependant, cela n'a aucun sens d'utiliser des fonctions qui dépendent de "Thing" depuis l'en-tête de l'élément. Il est plutôt logique que les fonctions utilisant "Thing" soient dans l'en-tête "Thing".

Si vous le regardez avec une approche orientée objet, quel que soit le langage de programmation, alors Element est une classe, Thing est une classe. La fonction peut être soit une fonction membre de Thing, soit une fonction non connexe utilisant cette classe. Ce que vous feriez en C orienté objet, est de déclarer à la fois "Element" et "Thing" comme les types incomplets dans leurs en-têtes respectifs. La définition de type est cachée à l'appelant et présente uniquement dans les fichiers C respectifs de ces en-têtes, appelés element.c et thing.c. Toutes les fonctions membres traitant des classes respectives seront déclarées dans les en-têtes et définies dans les fichiers C. (Cette conception est parfois appelée opaque type ou pointeurs opaques.)

Les fonctions utilisant l'une ou l'autre classe incluront simplement l'en-tête nécessaire.