Pointeur de déréférencement vers le type incomplet ‘struct ____’

J’essaie de créer un type en C pouvant accepter la plupart des types primitifs. Je suis nouveau en C et je ne comprends pas très bien les structures. Mon erreur se produit sur la ligne 10 (de main.c) et se produira également sur la ligne 11 si la ligne 10 est supprimée (également de main.c). Si quelqu’un a une idée ou un indicateur, je l’apprécierais vraiment! Merci beaucoup!

principal c:

#include  #include "modularType.h" int main() { int data = 1; PyType object = createPyObjectInt(data); printf("Type of data: %d\n", object->typeOfData); printf("Value of data: %d\n", object->intData); return 0; } 

modularType.h:

 typedef struct pytype *PyType; PyType createPyObjectEmpty(void); PyType createPyObjectInt(int data); void setDataInt(PyType, int data); void setDataIntStar(PyType, int* data); void freeMyType(PyType); void freeCharStar(PyType); void freeIntStar(PyType); void freeFloatStar(PyType); 

modularType.c:

 #include  #include  #ifndef NEW_TYPE #define NEW_TYPE #include "modularType.h" typedef enum { NO_DATA, REG_CHAR, CHAR_STAR, REG_INT, INT_STAR, REG_FLOAT, FLOAT_STAR, }types; struct pytype { //The number of data types i can hold here unsigned char typeOfData: 3; union { char charData; char* charStarData; int intData; int* intStarData; float floatData; float* floatStarData; } }; PyType createPyObjectEmpty(void) { PyType object; object = malloc(sizeof(*object)); object->typeOfData = NO_DATA; return object; } PyType createPyObjectInt(int data) { PyType object; object = malloc(sizeof(*object)); object->intData = data; object->typeOfData = REG_INT; return object; } void setDataInt(PyType object, int data) { object->intData = data; object->typeOfData = REG_INT; } void setDataIntStar(PyType object, int* data) { object->intStarData = data; object->typeOfData = INT_STAR; } #endif 

En outre, ma commande de compilation (gcc -Wall -std = c99 -o modType main.c modularType.c) génère l’avertissement suivant: modularType.c: 35: 1: avertissement: pas de point-virgule à la fin de la structure ou de l’union . Je pensais avoir correctement formaté ma structure, mais j’ai également vu des personnes définir les structures comme suit:

 typedef struct pytype { //code here }PyType; 

Est-ce une meilleure façon ou est-ce que je le fais bien?

La définition de la structure est incomplète dans le fichier d’en-tête, vous ne pouvez donc faire référence à aucun membre de la structure dans votre code. Le compilateur se plaint de ne connaître aucun membre de la structure.

Une définition de structure incomplète est une définition pour laquelle vous ne fournissez pas la liste des membres pour la mise en œuvre. Une telle définition vous permet de manipuler des pointeurs vers de telles structures, mais de ne pas accéder aux membres car ils ne sont pas définis explicitement et le compilateur doit connaître leur type et être décalés à partir du début de la structure pour générer le code correspondant.

De plus, le typedef PyType cache un pointeur sur un type de struct pytype . Il est sujette aux erreurs de cacher les pointeurs derrière les dactylographes, ce qui crée un code source de confusion pour le programmeur et le lecteur.

Le problème que vous avez est l’un de scope . C’est une partie intentionnelle et inhérente de C. L’approche que vous essayez d’adopter est l’ encapsulation ou la dissimulation de données . Vous déclarez intentionnellement la struct dans modularType.c qui fournit une étendue de fichier pour la structure. struct pytype n’est jamais exposé dans main.c il est donc impossible de référencer directement les membres de la structure (par exemple, object->foo ) dans main.c C’est par conception. C’est ainsi que vous masquez intentionnellement les membres de pytype d’un access direct à main .

Pour faire ce que vous tentez, vous devez exposer des fonctions via modularType.h qui modularType.h récupérer les informations souhaitées à partir de votre struct pytype object . Par exemple, vous souhaitez récupérer la valeur pour object->typeOfData et object->intData . Pour ce faire, vous avez simplement besoin de fonctions permettant d’accéder à ces données. Dans modularType.c vous pouvez append:

 int getPyObjectType (PyType object) { return object->typeOfData; } int getDataInt (PyType object) { return object->intData; } 

Ensuite, dans modularType.h vous pouvez fournir les prototypes de fonctions qui exposeront les fonctions à main , par exemple:

 int getPyObjectType (PyType); int getDataInt (PyType); 

Comme les deux fonctions sont en modularType.c , elles ont access aux membres de struct pytype tout ce qui se passe dans main . Après avoir apporté les modifications suivantes à main.c

 printf("Type of data: %d\n", getPyObjectType(object)); printf("Value of data: %d\n", getDataInt(object)); 

Vous pourrez retourner les valeurs que vous désirez, par exemple:

Exemple d’utilisation / de sortie

 $ ./bin/main Type of data: 3 Value of data: 1 

Référence 1: Même caMelCase ne s’agit pas d’une erreur, le style de codage standard pour C évite l’utilisation de noms de variables caMelCase ou MixedCase en faveur de tous les minuscules, tout en réservant des noms en majuscules à utiliser avec des macros et des constantes. C’est une question de style. C’est donc votre choix, mais si vous ne le suivez pas, vous risquez d’avoir une mauvaise première impression dans certains milieux.

Vous 2 problèmes:


  1. Cette partie de modularType.c appartient au début de modularType.h et il vous manque un ; (voir le commentaire dans l’extrait ci-dessous).

     typedef enum { NO_DATA, REG_CHAR, CHAR_STAR, REG_INT, INT_STAR, REG_FLOAT, FLOAT_STAR, } types; struct pytype { //The number of data types i can hold here unsigned char typeOfData: 3; union { char charData; char* charStarData; int intData; int* intStarData; float floatData; float* floatStarData; } ; // ^ you are missing a ';' here }; 

  1. La garde d’en-tête appartient à modularType.h et non à modularType.c

     #ifndef NEW_TYPE #define NEW_TYPE ... #endif 

    Ce n’est cependant pas un problème pour le moment. Cela n’empêche pas vos fichiers de comstackr, il est tout simplement inutile de mettre un garde d’en-tête dans un fichier .c.

La façon dont vous l’avez fait est bien, sauf pour 2 choses.

1) Vous ne devriez vraiment pas en faire une typedef à un pointeur d’une structure à moins que vous ne le précisiez à partir du nom qui est ce qu’il est. Changez-le en typedef struct pytype PyType;

2) Votre en-tête doit également inclure les définitions de struct pytype et de l’ struct pytype , de sorte que tout fichier qui l’inclut sache en quoi elles consistent.