【问题标题】:Declaration rule in struct typedefstruct typedef 中的声明规则
【发布时间】:2012-10-29 11:36:05
【问题描述】:

我正在阅读“C 编程语言”,遇到了关于 struct 的 typedef 的问题。代码是这样的:

typedef struct tnode *Treeptr;
typedef struct tnode { /* the tree node: */
    char *word; /* points to the text */
    int count; /* number of occurrences */
    struct tnode *left; /* left child */
    struct tnode *right; /* right child */
} Treenode;

到我们写作的时候

typedef struct tnode *Treeptr;

tnode 还没有被声明,但是我们没有得到任何编译错误, 但是当我们把上面的语句改成:

typedef Treenode *Treeptr;

我们得到编译错误:

error: parse error before '*' token
warning: data definition has no type or storage class

造成这种差异的原因是什么? “struct tnode”不是和“Treenode”一样吗?

【问题讨论】:

标签: c struct typedef declaration


【解决方案1】:

在定义之前,您不能使用类型。

使用typedef struct tnode { ... } Treenode; 声明,在到达分号之前不会定义类型Treenode。

typedef struct tnode *Treeptr; 的情况不同。这告诉编译器“有一个名为struct tnode 的结构类型,Treeptr 类型是指向struct tnode 的指针的别名”。在该声明的末尾,struct tnode 是一个不完整的类型。您可以创建指向不完整类型的指针,但不能创建不完整类型的变量(因此您可以定义 Treeptr ptr1; 或 struct tnode *ptr2;,它们是相同的类型,但您不能定义 struct tnode node;)。

struct tnode 的主体可以写成:

typedef struct tnode
{
    char    *word;
    int      count;
    Treeptr  left;
    Treeptr  right;
} Treenode;

因为Treeptr 在定义结构之前是struct tnode * 类型的已知别名。您不能使用Treenode *left;,因为Treenode 在到达最后一个分号之前是未知的别名(粗略地说)。

【讨论】:

    【解决方案2】:

    当您声明 TreePtr 时,您并未实现该结构。这被称为“前向声明”。类似于:“我们在这里使用它,但稍后我会更好地解释它”。该实现必须稍后出现,仅出现一次,这就是您在第二个typedef 中找到的内容。

    而TreePtr 与结构体不一样,因为TreePtr 实际上是一种新类型,包含了指针的事实。

    【讨论】:

    • 谢谢,Fèlix,很好的解释。所以你的意思是struct undefined_struct *a;是允许的,但是我们应该在我们说`struct undefined_struct b"之前实现undefined_struct,对吗?但是这个“转发声明”的意图是什么?
    • 前向声明或不完整类型在两种情况下可能会有所帮助。可以创建相互递归的结构,以便struct a 包含指向struct b 的指针,而struct b 包含指向struct a 的指针。这是深奥的(但如果无法进行前向声明,那将是一个真正的问题)。不完整类型的更重要的原因是,您可以根据指向不完整类型的指针定义一组函数的接口,并且公共标头不必显示结构内部的内容。它们是“不透明类型”,您正在使用信息隐藏。
    • 您可以根据需要任意组合执行struct undef a;、struct undef *b; 等操作。您可以将它们包含在另一个结构中。但是您必须在您喜欢的时间和地点声明结构的实现一次。
    • @FèlixGalindoAllué:我认为只有在取消引用或尝试创建结构类型的存储位置(而不是指向结构的指针)的情况下,才需要为结构提供任何定义类型)。如果指针类型从不用作不透明指针类型以外的任何东西,则无需为结构内容提供定义。
    【解决方案3】:

    typedef struct tnode *Treeptr; 行具有“tnode”结构的隐式前向声明。类似于:

    typedef struct tnode Treenode;
    typedef Treenode *Treeptr;
    
    struct tnode { /* the tree node: */
        char *word; /* points to the text */
        int count; /* number of occurrences */
        struct tnode *left; /* left child */
        struct tnode *right; /* right child */
    };
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-10-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-19
      相关资源
      最近更新 更多