8

考虑以下 C 代码片段:

typedef struct node{
    int val;
    struct node* left;
    struct node* right;
}node;

void inorderTraversal(node *p){
    inorderTraversal(p->left);
    printf("%d",p->val);
    inorderTraversal(p->right);
}

如果我只写typedef struct而不是,typedef struct node当我调用inorderTraversal(root). main()为什么即使程序没有显示任何错误,我也会收到此警告?

4

3 回答 3

11

如果你不给结构一个标签名称,

struct node* left;

在结构定义中声明了一个新的(不完整的)类型struct node。因此,当您传递一个指向该(不完整)类型node*的指针时,您需要传递一个不兼容类型的指针。

当您定义的结构具有指向同一类型的指针时,您必须能够在定义中命名该类型,因此该类型必须在范围内。

如果您给structa 名称,则类型 - 从那时起 - 在范围内并且可以被引用,尽管尚未完成,如struct node(如果标签是node)。在 typedef 完成后,该类型可以被称为struct nodeor 或node,无论您喜欢哪个。

但是如果你不给structa 标签,那么在 typedef 完成之前类型是匿名的,并且在此之前不能以任何方式被引用。而自从当线

struct node *left;

遇到,不知道struct node引用的类型,该行声明了一个新类型,struct node,其中一无所知。编译器没有理由将该类型与当前定义的类型联系起来。因此,此时,struct包含一个成员,该成员是指向未知不完整类型的指针。现在,在inorderTraversal,当你打电话

inorderTraversal(p->left);

with node *p,根据 的定义nodep->left是一个指向未知不完整类型的指针struct node。如果p已创建它p->left实际上是一个指向 的指针node,那么事情仍然会起作用(可能在指向不同类型的指针具有不同表示形式的平台上除外),但是您将指针传递给一种类型的指针,而该类型的指针需要指向不同类型的指针. 由于一种类型不完整,因此与预期类型不兼容。

于 2012-10-03T13:09:17.070 回答
0
"passing argument of incompatible pointer type"

因为当时节点是未知的。所以它被认为是一种新的类型。

struct node{
    int val;
    struct node* left;
    struct node* right;
};

void inorderTraversal(struct node *p){
    inorderTraversal(p->left);
    printf("%d",p->val);
    inorderTraversal(p->right);
}

现在 node 在使用它之前被声明为结构。即 struct node* left;没有错误。

另请参阅:自引用结构定义?
带有指向自身的指针的 C 结构体

于 2012-10-03T13:10:13.703 回答
-3

你不能创建一个匿名的typedef,它必须有一个名字。C 不支持匿名struct类型。

不过,GCC 扩展将启用该功能:-fms-extensions

于 2012-10-03T13:10:13.350 回答