取消引用指向不完整类型’struct ____’的指针

我试图在C中创建一个可以接受大多数原始类型的类型。 我是C的新手并且不太了解结构。 我的错误发生在第10行(main.c),如果第10行被删除(也是main.c),它也会出现在第11行。 如果有人有想法/指点我会非常感激! 非常感谢!

main.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 

作为旁注,我的编译命令(gcc -Wall -std = c99 -o modType main.c modularType.c)会产生以下警告: modularType.c:35:1:警告:在struct或union的末尾没有分号 。 我认为我已正确格式化了我的结构,但我也看到人们定义结构如下:

 typedef struct pytype { //code here }PyType; 

这是一种更好的方式还是我做得很好的方式?

头文件中的结构定义不完整,因此您不能在代码中引用任何结构成员。 编译器抱怨它根本不知道任何struct成员。

不完整的结构定义是指您不提供实现的成员列表的结构定义。 这样的定义允许您操作指向此类结构的指针,但不访问任何成员,因为它们未明确定义,并且编译器需要知道它们的类型和从结构的开头偏移以生成相应的代码。

同样不是typedef PyType隐藏了一个指向struct pytype的指针。 在typedef后面隐藏指针是容易出错的,这会导致程序员和阅读器的代码混乱。

你遇到的问题是范围问题 。 这是C的有意和固有的部分。您尝试采用的方法是数据封装数据隐藏 。 您有意在modularType.c声明了struct ,它为struct提供了文件范围struct pytype永远不会在main.c公开,因此无法在main.c中直接引用结构的成员(例如object->foo )。 那是设计上的。 这就是你故意隐藏pytype成员在pytype中直接访问的方式。

要执行您正在尝试的操作,您需要通过modularType.h公开函数,该函数从struct pytype object中检索所需的信息。 例如,您需要检索object->typeOfDataobject->intData 。 要在main执行此操作,您只需要提供对该数据的访问的函数。 在modularType.c您可以添加:

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

然后在modularType.h您可以提供将函数公开给main的函数原型,例如

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

由于这两个函数都在modularType.c ,因此它们可以访问struct pytype的成员,而main中的任何其他struct pytype都不能访问。 对main.c进行以下修改后

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

您将能够返回您想要的值,例如:

示例使用/输出

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

脚注1:虽然不是错误,但C的标准编码样式避免使用caMelCaseMixedCase变量名来支持所有小写,同时保留用于宏和常量的大写名称。 这是一个风格问题 – 所以它完全取决于你,但如果不遵循它可能会在某些圈子中产生错误的第一印象。

你有2个问题:


  1. modularType.c这一部分属于modularType.c的开头,你缺少一个; (请参阅右下方的注释片段)。

     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. 标题保护属于modularType.h而不属于modularType.c

     #ifndef NEW_TYPE #define NEW_TYPE ... #endif 

    然而,这不是一个问题。 它不会阻止您的文件编译,将标题保护放入.c文件中完全没用。

你做的方式很好,除了两件事。

1)你真的不应该把它作为结构指针的typedef,除非你从它的名字清楚地说明它。 将其更改为typedef struct pytype PyType;

2)您的标题还应包括struct pytype和enum的定义,以便包含它的任何文件都知道它们是什么。