我正在尝试在C中创建一个可以接受大多数原始类型的类型。我是 C 的新手,不太了解结构。我的错误发生在第 10 行(main.c),如果删除第 10 行(也是 main.c),它也会发生在第 11 行。如果有人有想法/指示,我将不胜感激!非常感谢!
主.c:
#include <stdio.h>
#include "modularType.h"
int main()
{
int data = 1;
PyType object = createPyObjectInt(data);
printf("Type of data: %dn", object->typeOfData);
printf("Value of data: %dn", object->intData);
return 0;
}
模块化类型.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);
模块化类型:
#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;
这是一种更好的方法还是我的做法很好?
头文件中的结构定义不完整,因此不能在代码中引用任何结构成员。编译器抱怨它根本不知道任何结构成员。
不完整的结构定义是指未提供实现的成员列表。这样的定义允许您操作指向此类结构的指针,但不能访问任何成员,因为它们没有显式定义,并且编译器需要知道它们的类型和结构开头的偏移量以生成相应的代码。
也不是说 typedefPyType
隐藏指向struct pytype
的指针。 将指针隐藏在 typedef 后面很容易出错,从而导致程序员和读者都混淆代码。
您遇到的问题是范围问题之一。这是C语言有意和固有的部分。您尝试采用的方法是数据封装或数据隐藏。您有意在modularType.c
中声明struct
,该为结构提供文件范围。struct pytype
永远不会公开main.c
因此无法直接引用结构的成员(例如object->foo
) 在main.c
.这是设计使然。这就是您有意隐藏pytype
成员不被直接访问的方式main
.
要执行您正在尝试的操作,您需要通过从struct pytype object
中检索所需信息的modularType.h
公开函数。例如,您希望检索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: %dn", getPyObjectType(object));
printf("Value of data: %dn", getDataInt(object));
您将能够返回所需的值,例如:
示例使用/输出
$ ./bin/main
Type of data: 3
Value of data: 1
脚注 1:虽然不是错误,但 C 的标准编码样式避免使用caMelCase
或MixedCase
变量名称,而支持所有小写,同时保留大写名称以用于宏和常量。这是一个风格问题 - 所以它完全取决于你,但如果不遵循它可能会导致某些圈子中的第一印象错误。
你 2 个问题:
-
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 文件中是完全没用的。
你这样做的方式很好,除了两件事。
1)你真的不应该把它变成一个结构的指针的typedef,除非你从名称中清楚地表明它是什么。将其更改为typedef struct pytype PyType;
2)你的标题还应该包括struct pytype
和枚举的定义,以便任何包含它的文件都知道它们是什么。