考虑以下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()
时,会收到一条警告,说“传递不兼容指针类型的参数”。为什么即使程序没有显示任何错误,我也会收到此警告?
答案 0 :(得分:10)
如果您没有为结构提供标签名称,
struct node* left;
结构定义中的声明了一个新的(不完整的)类型struct node
。因此,当您将指针传递给期望node*
的那个(不完整)类型时,您将传递一个不兼容类型的指针。
当您定义的结构具有指向同一类型的指针的成员时,您必须能够在定义中命名该类型,因此该类型必须在范围内。
如果您为struct
提供了一个名称,那么该类型就是 - 从该点开始 - 在范围内,可以作为struct node
引用(如果尚未完成)(如果标记为{{ 1}})。在typedef完成后,可以将该类型称为node
或struct node
,无论您喜欢哪种。
但是如果你没有给node
一个标签,那么在typedef完成之前,类型是匿名的,并且在此之前不能以任何方式引用。而且从那时起行
struct
遇到,struct node *left;
引用的类型都不知道,该行声明了一个新类型struct node
,其中没有任何已知的类型。编译器没有理由将该类型与当前正在定义的类型连接。所以在那时,struct node
包含一个指向未知不完整类型的指针的成员。现在,在struct
,当您致电
inorderTraversal
inorderTraversal(p->left);
,根据node *p
的定义,node
是指向未知不完整类型p->left
的指针。如果已创建struct node
以便p
实际上是指向p->left
的指针,那么事情仍然可行(除了可能在指向不同类型的指针具有不同表示的平台上),但是您&#39} ;将指针传递给一种类型,其中指向不同类型的指针。由于一种类型不完整,因此与预期类型不兼容。
答案 1 :(得分:1)
"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;
所以没有错误。
请参阅此内容:self referential struct definition?
C structure with pointer to self
答案 2 :(得分:-2)
您无法创建匿名typedef
,它必须具有名称。 C不支持匿名struct
类型。
GCC扩展程序将启用该功能:-fms-extensions