2012-11-09 118 views
6

我正在阅读'The C Programming Language',并且遇到关于typedef struct的问题。该代码是这样的: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 

是什么导致差异? “结构tnode”不是“Treenode”吗?

+0

您可能会发现[C标准的哪个部分允许此代码编译?](http://stackoverflow.com/questions/12200096/which-part-of-the-c-standard-allows-this-code C++标准是否认为这个头文件中有一个或两个'struct uperms_entry'类型?](http://stackoverflow.com/questions/11697705/does-the-c-standard-consider -that-one-or-two-struct-uperms-entry-typ)作为相关内容,但它们可能会超出你所在的级别。 –

回答

6

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

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在达到最终分号(粗略地说)之前不是已知的别名。

0

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 */ 
}; 
1

当您声明TreePtr时,您没有实现该结构。这就是所谓的“正向声明”。类似于:“我们在这里使用这个,但稍后我会更好地解释它”。该实现必须稍后才会出现,只有一次,这就是您在第二个typedef中找到的内容。

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

+0

谢谢,Fèlix,很好的解释。所以你的意思是'struct undefined_struct * a;'是允许的,但是在我们说'struct undefined_struct b'之前我们应该实现'undefined_struct',是吗?但是这个“_foward declaration_”的意图是什么? – Rain

+1

前向声明,或不完整的类型在两种情况下可能会有所帮助,可以创建相互递归的结构,以便'struct a'包含一个指向'struct b'的指针,'struct b'包含一个指向'struct a'的指针。这是很深奥的(但是如果不能进行前向声明,这将是一个真正的问题)。不完整类型的更多原因是你可以根据指向不完整类型的指针定义接口到一组函数,并且公共头文件不需要揭示结构中的内容;它们是一种“不透明类型”,并且您正在使用信息隐藏功能 –

+0

您可以按照任意组合执行诸如“struct undef a;”,“struct undef * b;”等操作,如就像你需要的一样,你可以包括将它们放在另一个结构中。但是你必须在你喜欢的地方和时间声明结构的实现。 –