我已经习惯了以下代码。
但C编译器如何解决循环定义问题?或者这个问题真的存在吗?
struct node {
int data;
struct node *next; // circular definition for "struct node" type?
};
或者,在32位机器上,我是否可以将struct node * next
成员视为32位无符号整数类型的成员?这让我感觉好多了。
我认为循环定义的原因是,当编译器遇到类似next -> data
或next -> next
的内容时,它必须知道要添加到每个成员的确切偏移量 next
指针,用于获取每个成员的正确位置。这种计算需要了解每个成员的类型。因此,对于成员next
,可能会出现循环定义问题:
next
的类型为struct node *
,struct node
类型 包含next
,next
的类型为struct node *
...
编译器如何计算sizeof(struct node)
?
嗯,我认为理解这个看似圆形的问题的关键概念是,指针的大小与它指向的类型无关。并且特定计算机上的大小固定。在编译时,指针的类型仅有意义,编译器可以生成指针计算指令。
答案 0 :(得分:7)
next
是struct node *
,它只是一个指针,而不是struct node
,因此没有实际的循环定义。不需要结构的细节来弄清楚如何指向它。
要解决您的附录:
struct node
和struct node *
是完全不同的类型。 struct node *
不包含任何其他对象。答案 1 :(得分:1)
让我按顺序回答你的问题:
但C编译器如何解决循环定义问题?
struct node *next;
不是循环定义,struct node
是不完整的类型,next
被定义为类型struct node *
的成员,它只是一个指针。
或者这个问题真的存在吗?
不,不是真正的问题。事实上,您可以将成员定义为指向任何未定义结构的指针。
或者,在32位机器上,我是否可以将
struct node *next
成员视为32位无符号整数类型的成员?
您不应对结构构件的实际尺寸,偏移或对齐做出任何假设。 32位机器的指针大小不是32位,只要你将它们用作指针而不是整数就没关系。
我认为循环定义的原因是,当编译器遇到
next->data
或next->next
之类的东西时,它必须知道要添加到next
指针的每个成员的确切偏移量获得每个成员的正确位置。
这是正确的,但是当编译器解析这样的代码时,结构定义已经完成,它可以确定data
和next
成员的偏移量。
编译器如何计算
sizeof(struct node)
?
在解析结构定义之后,编译器具有计算结构实例大小所需的所有信息。对于这样的计算,假设所有指向结构和/或联合的指针具有相同的大小。
嗯,我认为理解这个看似循环的问题的关键概念是,指针的大小与它指向的类型无关。并且尺寸固定在特定的机器上。指针的类型仅在编译时有意义,编译器才能生成指针计算指令。
指针大小 与其指向的类型相关,并且在某些体系结构上,不同的指针类型可能具有不同的大小。然而,C标准规定了一些限制因素:
void *
并返回。在大多数现代架构上,特别是在Posix兼容系统上,所有标准指针类型都具有相同的大小。