我试图在C中创建一个可以接受大多数原始类型的类型。我是C的新手,并且不太了解结构。我的错误发生在第10行(main.c),如果第10行被删除(也是main.c),它也会出现在第11行。如果有人有想法/指点我会非常感激!非常感谢!
main.c中:
#include <stdio.h>
#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 <stdlib.h>
#include <stdio.h>
#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:警告:结束时没有分号结构或联合。我认为我已正确格式化了我的结构,但我也看到人们将结构定义如下:
typedef struct pytype
{
//code here
}PyType;
这是一种更好的方式还是我做得很好的方式?
答案 0 :(得分:4)
您遇到的问题是范围之一。这是C的有意和固有的部分。您尝试采用的方法是数据封装或数据隐藏之一。您有意在struct
中声明了modularType.c
,它为结构提供了文件范围。 struct pytype
中永远不会公开main.c
,因此无法直接引用object->foo
中结构的成员(例如main.c
)。那是设计上的。这就是故意隐藏pytype
成员在main
中被直接访问的方式。
要执行您尝试的操作,您需要通过modularType.h
公开函数,以便从struct pytype object
中检索所需的信息。例如,您要检索object->typeOfData
和object->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
的成员。对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的标准编码样式避免使用caMelCase
或MixedCase
变量名来支持所有 lower-大小写,同时保留大写名称,以便与宏和常量一起使用。这是一个风格问题 - 所以它完全取决于你,但如果不遵循它可能会在某些圈子中产生错误的第一印象。
答案 1 :(得分:3)
头文件中的结构定义不完整,因此您无法在代码中引用任何结构成员。编译器抱怨它根本不知道任何结构成员。
不完整的结构定义是指您不提供实施成员列表的定义。这样的定义允许您操作指向此类结构的指针,但不访问任何成员,因为它们未被显式定义,并且编译器需要知道它们的类型和从结构的开头偏移以生成相应的代码。
同样不是typedef PyType
隐藏了指向struct pytype
的指针。它很容易隐藏在typedef后面的指针,导致程序员和读者的代码混乱。
答案 2 :(得分:1)
你有两个问题:
modularType.c
中的这一部分属于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;
} ;
// ^ you are missing a ';' here
};
标题后卫属于modularType.h
而不属于modularType.c
#ifndef NEW_TYPE
#define NEW_TYPE
...
#endif
现在这不是问题。它不会阻止您的文件编译,将标题保护放入.c文件中完全没用。
答案 3 :(得分:-1)
你做的方式很好,除了两件事。
1)你真的不应该把它变成一个结构指针的typedef,除非你从它的名字中清楚地说明它。将其更改为typedef struct pytype PyType;
2)您的标题还应包括struct pytype
和枚举的定义,以便包含它的任何文件都知道它们是什么。