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 代码在其他一些不相关的文件中执行不应该执行的操作。