Typedef,标记和未标记的结构以及不兼容的指针类型

Vai*_*wal 8 c struct 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);
}
Run Code Online (Sandbox Code Playgroud)

如果我只写typedef struct,而不是typedef struct node,我得到一个警告说"通过兼容的指针类型的参数"当我打电话inorderTraversal(root)main().为什么即使程序没有显示任何错误,我也会收到此警告?

Dan*_*her 10

如果您没有为结构提供标记名称,

struct node* left;
Run Code Online (Sandbox Code Playgroud)

在struct定义中声明一个新的(不完整的)类型struct node.因此,当您将指针传递给node*期望值为a(不完整)的类型时,您将传递一个不兼容类型的指针.

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

如果你给出struct一个名字,那么类型是 - 从那一点开始 - 在范围内,并且可以被引用,虽然还没有完整,但是struct node(如果标签是node).在typedef完成后,可以将类型称为struct node或者node,无论您喜欢哪种类型.

但是如果你没有给出struct一个标签,那么在typedef完成之前,类型是匿名的,并且在此之前不能以任何方式引用.而且从那时起

struct node *left;
Run Code Online (Sandbox Code Playgroud)

遇到,没有struct node引用的类型是已知的,该行声明了一个新类型,struct node其中没有任何已知的.编译器没有理由将该类型与当前正在定义的类型连接.所以在那一点上,struct包含一个指向未知不完整类型的指针的成员.现在,在inorderTraversal你打电话的时候

inorderTraversal(p->left);
Run Code Online (Sandbox Code Playgroud)

node *p,通过的定义node,p->left是一个指针,指向未知不完整的类型struct node.如果p已经创建了p->left它实际上是指向的node东西,那么事情仍然会起作用(除了可能在指向不同类型的指针具有不同表示的平台上),但是你将指针传递给一种类型,其中指向不同类型的指针是预期的.由于一种类型不完整,因此与预期类型不兼容.