4

我在 Windows 上使用 MinGW。我正在构建链表,对此我感到困惑。

#include <stdio.h>
#include <stdlib.h>

typedef struct Data
{
    int x;
    int y;
    struct BlaBla * next;               /*compiles with no problem*/
}List;

int main(void)
{
    List item;
    List * head;
    head = NULL;
    return 0;
}

我现在该结构不能具有结构变量(对象,该结构的实例),但可以具有该结构类型的指针。不知道指针可以是不存在类型的指针。struct BlaBla * next;(不是链表,它必须struct Data * next是泛泛之谈)

4

4 回答 4

6

是的,您可以,因为编译器在第一次遇到未知类型名称时,会假定存在具有此名称的结构类型定义。然后它将为您前向声明结构名称,让您将其用作指针,但您不能取消引用它,也不能对其进行指针运算(因为它是不完整的类型)。

于 2013-03-20T05:26:19.493 回答
3

编译器将接受例如您的示例的代码:

typedef struct Data
{
    int x;
    int y;
    struct BlaBla * next;               /*compiles with no problem*/
}List;

这没关系,因为编译器知道指针的大小,并且编译器假设结构将在取消引用之前定义。

因为编译器以这种方式运行,所以可以这样做:

typedef struct Data
{
    int x;
    int y;
    struct Data * next;     /* points to itself */
} List;

但是,如果您要包含内联结构,如下所示:

typedef struct Data
{
    int x;
    int y;
    struct BlaBla blaStruct;               /* Not a pointer. Won't compile. */
}List;

编译器无法计算出有多大struct Data,因为它不知道struct BlaBla有多大。要编译它,您需要包含struct BlaBla.

请注意,只要您需要访问 的成员struct BlaBla,您就需要包含定义它的头文件。

于 2013-03-20T05:31:53.550 回答
0

这取决于您所说的“不存在”是什么意思。如果你甚至没有声明 BlaBla,你会得到一个错误。

如果您已声明它但尚未定义它,那将正常工作。您可以拥有指向不完整类型的指针。

事实上,这是在 C中处理不透明指针的正常方式。

因此,您可能会认为这是无效的,因为struct BlaBla在范围内没有声明:

typedef struct Data {
    struct BlaBla *next;  // What the ??
} List;

但是,它实际上没关系,因为它同时声明struct BlaBla和定义next

当然,由于定义意味着声明,这也是可以的:

struct BlaBla { int xyzzy; };
typedef struct Data {
    struct BlaBla *next;  // What the ??
} List;
于 2013-03-20T05:26:18.010 回答
0

为了声明给定类型的变量或字段,将一个作为参数传递,或将一个复制到另一个相同类型,编译器必须知道变量或字段占用多少字节,它有什么对齐要求(如果any),以及它兼容的其他指针类型,但这就是编译器需要知道的全部内容。在 C 的所有常见方言中,指向任何结构的指针将始终具有相同的大小并需要相同的对齐方式,而不管它指向的结构的大小或该结构可能包含的内容,并且指向任何结构类型的指针仅与指向相同结构类型的其他指针兼容。

因此,除了分配空间来保存指针本身(与它们指向的结构相反)、将它们作为参数传递或将它们复制到其他指针之外,不需要对指向结构的指针做任何事情的代码不会除了其唯一名称之外,不需要知道关于它们指向的结构类型的任何信息。需要为结构分配空间(而不是指向结构的指针)或访问其任何成员的代码必须更多地了解其类型,但不做这些事情的代码不需要此类信息。

于 2013-03-20T14:57:48.090 回答