在《The C programming language, second edition》的 section A8.3 中,有这么一段话:
A structure may not contain a member of incomplete type. Therefore, it is impossible to declare a structure or union containing an instance of itself. However, besides giving a name to the structure or union type, tags allow definition of self-referential structures; a structure or union may contain a pointer to an instance of itself, because pointers to incomplete types may be declared.
我对 it is impossible to declare a structure or union containing an instance of itself.
百思不得其解,因此探索了一番。
原因(中文)
在 C 编程中,不可能直接声明一个包含自身实例的结构体或联合体。这个限制被称为"自引用"或"递归"声明,与内存分配和结构体大小确定的方式有关。
当声明一个结构体或联合体时,编译器需要知道结构体的大小以便为其分配内存。然而,如果一个结构体包含自身的实例,结构体的大小就变得不确定,无法确定。
我们来举个例子来说明这个问题:
|
|
在上面的例子中,定义了一个 Node
结构体,其中包含了同样是 Node
结构体类型的成员 next
。问题在于编译器无法确定 Node
的大小,因为它取决于 next
的大小,而 next
又是一个 Node
结构体。这就形成了递归定义,导致结构体的大小变得无限大。
为了解决这个限制,可以使用指针来实现自引用的行为。以下是一个更新后的示例:
|
|
在这个修改后的示例中,next
成员被声明为指向 Node
结构体的指针(struct Node*
),而不是直接嵌套一个结构体实例。指针的大小是固定的,不管它指向的类型是什么,因此可以正确确定结构体的大小。
通过使用指针,可以创建链式结构或递归数据结构,其中每个节点指向另一个节点,从而实现更灵活和动态的内存分配。
总结起来,在C语言中无法直接声明包含自身实例的结构体或联合体,是因为难以确定这种结构体的大小。但是,可以使用指针来实现类似的自引用行为,创建递归或链式数据结构。
answer
In C programming, it is not possible to declare a structure or union that contains an instance of itself directly. This limitation is known as “self-referential” or “recursive” declaration, and it is related to the way memory is allocated and the size of the structure is determined.
When a structure or union is declared, the compiler needs to know the size of the structure in order to allocate memory for it. However, if a structure contains an instance of itself, the size of the structure becomes indefinite and cannot be determined.
Let’s take an example to illustrate this issue:
|
|
In the above example, the Node
structure is defined with a member next
of the same structure type Node
. The problem here is that the compiler cannot determine the size of Node
because it depends on the size of next
, which is itself a Node
structure. This creates a recursive definition and leads to an infinite size for the structure.
To overcome this limitation, you can use pointers to achieve self-referential behavior. Here’s an updated example:
|
|
In this modified example, the next
member is declared as a pointer to the Node
structure (struct Node*
), rather than directly embedding an instance of the structure. Pointers have a fixed size, regardless of the type they are pointing to, so the size of the structure can be determined correctly.
By using pointers, you can create linked structures or recursive data structures where each node points to another node, allowing for more flexible and dynamic memory allocation.
In summary, the inability to declare a structure or union containing an instance of itself directly in C is due to the challenge of determining the size of such a structure. However, you can use pointers to achieve similar self-referential behavior and create recursive or linked data structures.