sizeof error : incomplete type is not allowed
sizeof error : incomplete type is not allowed
我有几个 C 源文件和头文件,每个 ADT 都有一个 .h
文件。
其中之一称为锦标赛。当我尝试在 tournament.h
中为锦标赛 malloc 内存时,没有发生任何问题,但是当我在不同的 c 文件中执行此操作时,出现以下错误
“不允许不完整的类型”
这是在tournament.h
中定义锦标赛的方式
typedef struct tournament_t *Tournament;
ps: 有人说对结构体进行 typedef 是件坏事,但我必须这样做,因为导师想要它。
这就是 tournament.c
中的情况,我没有遇到任何问题
struct tournament_t
{
//fields
};
Tournament tournamentCreate()
{
Tournament new=malloc(sizeof(*new));
if(!new)
{
return NULL;
}
//I don't get any error here
}
但是,在名为 chess.c
的文件中,会发生以下情况:
#include "tournament.h"
static Tournament copyTournament(Tournament tournament)
{
if (!tournament) {
return NULL;
}
Tournament copy = malloc(sizeof(*copy));//here I get the error
if (!copy)
{
return NULL;
}
}
PS:最后一个函数必须是 static
,因为教师再次希望它是。
如果您需要更多信息来解决它,请告诉我。
typedef struct tournament_t *Tournament;
用作结构的 前向声明 。此时在 header 文件中,编译器不知道该结构的内容。这意味着您需要在别处编写结构定义,否则结构将重命名为未知 - 不完整的类型。
然后将结构定义放在 tournament.c 中。这意味着 翻译单元 中的编译器现在可以看到结构内容。翻译单元表示 .c 文件及其包含的所有 header。
这反过来意味着您可以自由使用 tournament.c 中的结构成员。但是 chess.c 看不到它们。因为是不同的翻译单位。它只能看到 header 中的前向声明,因此它仍然是 chess.c.
的不完整类型
如果你在没有指针声明的情况下将 typedef 写成 typedef struct tournament_t Tournament;
,那么 chess.c 甚至无法声明这种类型的 object,因为它不不知道结构是如何构建的。但是,它可以声明指向不完整类型的 object 的指针 - 您可以拥有一个指针,但不知道它指向的内容的详细信息。
这很可能是设计使然,这种方法被称为“不透明类型”,是您在 C 中设计私有封装的方式,以防止程序的其余部分访问结构的成员。
some people say it's a bad thing to typedef a struct but I have to do it since the instructors want it.
是否将 typedef 与结构结合使用是 100% 主观的编码风格,没有对错之分。但是,将指针与 typedef 一起使用通常会出现问题,因为它会诱使程序员认为他们拥有的是普通的 object 而不是指针。在您的情况下,它会诱使您相信您可以访问该结构。
由于它是一个不完整的类型,您不能在 tournament.c 之外声明它的 object。您也不能在这样的 object 上使用 sizeof
。这就是编译器错误的原因。
你应该通过让 tournament.h 提供一个复制 object 的函数来解决这个问题,而这个函数又应该在 tournament.c 中实现。请注意“不透明类型”如何迫使您进行正确的程序设计,而不是让 non-related 代码在其他一些不相关的文件中执行不应该执行的操作。
我有几个 C 源文件和头文件,每个 ADT 都有一个 .h
文件。
其中之一称为锦标赛。当我尝试在 tournament.h
中为锦标赛 malloc 内存时,没有发生任何问题,但是当我在不同的 c 文件中执行此操作时,出现以下错误
“不允许不完整的类型”
这是在tournament.h
中定义锦标赛的方式typedef struct tournament_t *Tournament;
ps: 有人说对结构体进行 typedef 是件坏事,但我必须这样做,因为导师想要它。
这就是 tournament.c
中的情况,我没有遇到任何问题
struct tournament_t
{
//fields
};
Tournament tournamentCreate()
{
Tournament new=malloc(sizeof(*new));
if(!new)
{
return NULL;
}
//I don't get any error here
}
但是,在名为 chess.c
的文件中,会发生以下情况:
#include "tournament.h"
static Tournament copyTournament(Tournament tournament)
{
if (!tournament) {
return NULL;
}
Tournament copy = malloc(sizeof(*copy));//here I get the error
if (!copy)
{
return NULL;
}
}
PS:最后一个函数必须是 static
,因为教师再次希望它是。
如果您需要更多信息来解决它,请告诉我。
typedef struct tournament_t *Tournament;
用作结构的 前向声明 。此时在 header 文件中,编译器不知道该结构的内容。这意味着您需要在别处编写结构定义,否则结构将重命名为未知 - 不完整的类型。
然后将结构定义放在 tournament.c 中。这意味着 翻译单元 中的编译器现在可以看到结构内容。翻译单元表示 .c 文件及其包含的所有 header。
这反过来意味着您可以自由使用 tournament.c 中的结构成员。但是 chess.c 看不到它们。因为是不同的翻译单位。它只能看到 header 中的前向声明,因此它仍然是 chess.c.
的不完整类型如果你在没有指针声明的情况下将 typedef 写成 typedef struct tournament_t Tournament;
,那么 chess.c 甚至无法声明这种类型的 object,因为它不不知道结构是如何构建的。但是,它可以声明指向不完整类型的 object 的指针 - 您可以拥有一个指针,但不知道它指向的内容的详细信息。
这很可能是设计使然,这种方法被称为“不透明类型”,是您在 C 中设计私有封装的方式,以防止程序的其余部分访问结构的成员。
some people say it's a bad thing to typedef a struct but I have to do it since the instructors want it.
是否将 typedef 与结构结合使用是 100% 主观的编码风格,没有对错之分。但是,将指针与 typedef 一起使用通常会出现问题,因为它会诱使程序员认为他们拥有的是普通的 object 而不是指针。在您的情况下,它会诱使您相信您可以访问该结构。
由于它是一个不完整的类型,您不能在 tournament.c 之外声明它的 object。您也不能在这样的 object 上使用 sizeof
。这就是编译器错误的原因。
你应该通过让 tournament.h 提供一个复制 object 的函数来解决这个问题,而这个函数又应该在 tournament.c 中实现。请注意“不透明类型”如何迫使您进行正确的程序设计,而不是让 non-related 代码在其他一些不相关的文件中执行不应该执行的操作。