当struct中的指针指向struct本身时,C如何解析循环定义?

我已经习惯了以下代码。

但是C编译器如何解决循环定义问题? 或者这个问题真的存在吗?

struct node { int data; struct node *next; // circular definition for "struct node" type? }; 

添加1

或者,在32位机器上,我可以稍微将struct node * next成员视为32位无符号整数类型的成员吗? 这让我感觉好多了。

添加2

我想到循环定义的原因是,当编译器遇到类似next -> datanext -> next ,它必须知道要添加到next指针的每个成员的确切偏移量 ,以获得每个成员的正确位置。 而这种计算需要了解每个成员的类型 。 因此,对于next的成员,可能会出现循环定义问题:

接下来的类型是struct node *struct node类型包含nextnext类型是struct node *

添加3

编译器如何计算sizeof(struct node)

添加4

好吧,我认为理解这个看似循环的问题的关键概念是,指针的大小与它指向的类型无关。 并且尺寸固定在特定的机器上。 指针的类型在编译时有意义,以便编译器生成指针计算指令。

next是一个struct node * ,它只是一个指针,而不是一个struct node ,因此没有实际的循环定义。 不需要结构的细节来弄清楚如何指向它。

要解决您的附录:

  1. 虽然这或多或少准确并且可能会起作用,但标准并不保证,你不应该这样做。
  2. 同样, struct nodestruct node *是完全不同的类型。 struct node *不包含任何其他对象。

让我按顺序回答你的问题:

但是C编译器如何解决循环定义问题?

struct node *next; 不是循环定义, struct node是不完整的类型, next定义为类型为struct node *的成员,它只是一个指针。

或者这个问题真的存在吗?

不,不是真正的问题。 事实上,您可以将成员定义为指向任何未定义结构的指针。

或者,在32位机器上,我可以稍微将struct node *next成员视为32位无符号整数类型的成员吗?

您不应对结构构件的实际尺寸,偏移或对齐做出任何假设。 32位机器的指针大小可能不是32位,只要你将它们用作指针而不是整数就没关系。

我认为循环定义的原因是,当编译器遇到类似next->datanext->next ,它必须知道要添加到next指针的每个成员的确切偏移量以获得每个成员的正确位置。

这是正确的,但是当编译器解析这样的代码时,结构定义就完成了,它可以确定datanext成员的偏移量。

编译器如何计算sizeof(struct node)

在解析结构定义之后,编译器具有计算结构实例大小所需的所有信息。 对于这样的计算,假设所有指向结构和/或联合的指针具有相同的大小。

好吧,我认为理解这个看似循环的问题的关键概念是,指针的大小与它指向的类型无关。 并且尺寸固定在特定的机器上。 指针的类型仅在编译时有意义,以便编译器生成指针计算指令。

指针大小与它指向的类型相关,并且在某些体系结构上,不同的指针类型可能具有不同的大小。 然而,C标准规定了一些限制:

  • 所有指针类型都可以转换为void *和back。
  • 所有结构和工会的指针都有相同的大小。

在大多数现代架构上,特别是在符合Posix的系统上,所有标准指针类型都具有相同的大小。