根据语言标准,它们是有效的,因此应该被允许。
现在,如果你问这一切是如何运作的,这很容易。
通常,指针只是内存地址。如果对象由整数字节表示(每个字节都有唯一的地址),则您可以拥有指向内存中任何对象的指针。我在这里说“整数”是因为你不能有一个指向结构位字段的指针(至少,你不能有一个指向那些不在字节边界开始并占据整数字节的指针) .
因此,Ptr2
它只是一个预先知道大小的指针类型(如果您的 CPU 的地址空间是从 0 到 4 GB,则 32 位地址足以寻址每个字节,而 32 位将是该 CPU 上的本机指针大小)并且您可以为这样的指针分配空间,struct Rec1
即使struct Rec2
该指针指向的内容尚不知道,这就是我们在相关代码中所拥有的。Ptr1
并且Ptr2
被定义为不完整的类型,这是它的正式名称。
在语言中实现这种不完整指针类型的基本原理是非常实用的。如果要创建链接列表或树,它们的元素或节点必须以某种方式指向与它们链接的其他元素或节点。理论上,您可以为最后一个元素(或叶节点)创建不同的元素/节点类型,然后为指向它的元素创建不同的元素/节点类型,然后为指向该元素的元素创建不同的元素/节点类型,依此类推。但这不能很好地扩展,如果您有多个元素或节点。如果你想要一百万个呢?定义一百万个几乎相同的类型充其量是不切实际的。因此,该语言为您提供了避免这种情况的捷径。您也可以将next
指针声明为只是void*
指针,但随后您需要将它们强制转换为struct Rect1*
或struct Rect2*
并且此类代码的维护和调试将容易出错。所以,在那里,语言可以帮助你。