我们在学校有一个作业,我们有一个头文件和我们 需要实施它。标题定义:
typedef struct Board* BoardP;
据我所知,BoardP是指向struct Board的指针。 无论如何,我的实现是:
typedef struct Board
{
int width;
int height;
char *board;
} *BoardP;
但我一直在接受:
Board.c:21: error: redefinition of typedef ‘BoardP’
Board.h:4: note: previous declaration of ‘BoardP’ was here
关于为什么会发生这种情况的任何想法?谢谢!
编辑:另一个问题。正如您所看到的,我的struct包含一个字符数组。当我编写一个构造函数时,我应该首先初始化(malloc(sizeof(height * width))数组然后是struct吗?如何使用free()?我应该首先释放数组然后释放结构吗? 感谢答案 0 :(得分:5)
从定义中删除typedef
。
struct Board
{
int width;
int height;
char *board;
};
结构是一个结构;它不像你总是typedef
那样。说实话,我opaque pointers仅typedef structs
。
来自style(9)
:
避免将typedef用于结构类型。 Typedef有问题 因为他们没有正确隐藏他们的基础类型;例如 你需要知道typedef是结构本身还是指针 结构。另外必须正好宣布一次, 而不完整的结构类型可以多次提及 必要的。
答案 1 :(得分:1)
之所以发生这种情况,是因为在您预先编写的头文件中,您必须为其编写实现,已经将数据类型struct Board *
键入“新”数据类型{{1} }。您对BoardP
是指向数据类型BoardP
的指针的解释是正确的。
但是,为了使头文件中的代码有效,您只需要定义缺少的内容,在本例中,只需要实现struct Board
数据类型。
如果您在头文件中还没有typedef,那么您提出的解决方案就可以使用。
正如您在头文件中已经有的那样,只有cnicutar提出的代码(没有struct Board
的代码)应该放在 .c 文件中。
答案 2 :(得分:-1)
关于你的第二个问题......
您可以按照您喜欢的顺序malloc
,但我通常在尝试分配任何子对象之前分配对象本身,因为这样您就可以清楚地存储子对象{{1}的结果s(在结构中)而不是必须将它们存储在其他无用的临时变量中。
请务必正确处理错误 - 如果第二个malloc
失败,您需要malloc
第一个错误。这实际上是许多C程序员喜欢使用free
:
goto
当您struct Board *makeBoard(...)
{
struct Board *b = malloc(sizeof *b);
if(b == NULL) goto end1;
b->board = malloc(...);
if(b->board == NULL) goto end2;
// ...
end2:
free(b);
end1:
return NULL;
}
数据时,在释放主对象之前必须free
子对象,除非在free
主要对象之前存储指向临时变量中所有子对象的指针宾语。也就是说,以下内容不起作用:
free
因为在第二个声明中,free(b);
free(b->board);
为b
d,无法安全地取消引用。以相反的顺序做这件事是最干净的。