Typedef,标记和未标记的结构以及不兼容的指针类型
请考虑以下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
,当我在main()
调用inorderTraversal(root)
时,我会收到一条警告,说“传递不兼容指针类型的参数”。 为什么即使程序没有显示任何错误,我也会收到此警告?
如果您没有为结构提供标记名称,
struct node* left;
在struct定义中声明一个新的(不完整的)类型struct node
。 因此,当您将指针传递给期望node*
那个(不完整)类型时,您将传递一个不兼容类型的指针。
当您定义的结构具有指向同一类型的指针的成员时,您必须能够在定义中命名该类型,因此该类型必须在范围内。
如果给struct
命名,那么类型是 – 从那时开始 – 在范围内,并且可以作为struct node
(如果标记是node
)引用(尽管尚未完成)。 在typedef完成之后,可以将类型称为struct node
或node
,无论您喜欢哪个。
但是如果你没有给struct
一个标签,那么在typedef完成之前,类型是匿名的,并且在此之前不能以任何方式引用。 而且从那时起
struct node *left;
如果遇到struct node
引用的类型,则该行声明一个新类型struct node
,其中没有任何已知的类型。 编译器没有理由将该类型与当前正在定义的类型连接。 所以在那时, struct
包含一个成员,该成员是指向未知不完整类型的指针。 现在,在inorderTraversal
,当你打电话时
inorderTraversal(p->left);
对于node *p
,通过node
的定义, p->left
是指向未知不完整类型struct node
的指针。 如果已经创建了p->left
使得p->left
实际上是指向node
的指针,那么事情仍然可以工作(除了可能在指向不同类型的指针具有不同表示的平台上),但是你将指针传递给指针的一种类型预期到不同的类型。 由于一种类型不完整,因此与预期类型不兼容。
"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。 即struct node* left;
所以没有错误。
请参考这个: 自引用结构定义?
指向自我的C结构
您无法创建匿名typedef
,它必须具有名称。 C不支持匿名struct
类型。
GCC扩展将启用该function: -fms-extensions