首页 > 解决方案 > C 类型语法如何避免循环定义?

问题描述

此陈述和示例来自Nick Parlante 的 Essential C。

C 类型语法的一个好处是它避免了当指针结构需要引用自身时出现的循环定义问题。以下定义定义了链表中的一个节点。请注意,不需要预先声明节点指针类型。

   struct node {
      int data;
      struct node* next;
   };

struct node*当它仍在结构节点内时,C 编译器如何知道它是什么。

还有另一个循环定义的例子,其中一个类型struct treenode*在被进一步定义之前被使用。

typedef struct treenode* Tree;
struct treenode {
    int data;
    Tree smaller, larger;   // equivalently, this line could say
                            // "struct treenode *smaller, *larger"
};

C 编译器如何知道struct treenode*尚未定义的内容。

相关SO问题:当结构中的指针指向结构本身时,C如何解析循环定义?(这是相关的,它不回答“如何”的问题)。

编辑:我假设 C 编译器能够一次性完成此操作。

标签: cpointers

解决方案


C 标准在§6.2.5 Types ¶28中规定(强调):

指向 void 的指针应具有与指向字符类型的指针相同的表示和对齐要求。48)同样,指向兼容类型的合格或不合格版本的指针应具有相同的表示和对齐要求。所有指向结构类型的指针都应具有彼此相同的表示和对齐要求。所有指向联合类型的指针都应具有彼此相同的表示和对齐要求。指向其他类型的指针不需要具有相同的表示或对齐要求。

因此,C 编译器知道如何处理任何结构指针类型,因为所有结构指针必须具有相同的表示和对齐要求。无论您嵌入 astruct node *还是 a都适用struct value *——无论编译器之前是否知道 type struct value。这也有助于“不透明类型”——您可以拥有指向编译器不知道结构内容的结构类型的指针。

你不能做的struct nodestruct node *struct node. 您可以将以前已知的结构类型作为值嵌入到结构中。您还可以在另一个中定义结构类型:

struct node
{
    int data;
    struct node *next;
    struct key_value
    {
        int key;
        char *value;
    } kv;
};

与 C++ 不同,该struct key_value类型可用而没有范围问题——它不限于在 type 中使用struct node。这不是好的编码习惯,但它是允许的。


推荐阅读