引用匿名结构体本身

4
typedef struct {
    //
} list;

vs

typedef struct list{
    //
} list;

我在其他帖子中阅读到(例如使用匿名结构体与具有typedef的命名结构体),这些帖子说这两种方式几乎相同,只有在引用结构本身时才需要后者。

然而,以下代码在clang和gcc中都可以编译通过:

#include <stdio.h>

typedef struct {
    struct list *next;
} list;

int main(){
 list l;
 return  0;
}

上面我有一个匿名结构体引用自身。这是如何编译通过的?

1
struct list and list are different types . Struct tags have a different "namespace" to typedef names. You will encounter problems if you try to point next to a list - M.M
2
你正在声明 next 作为指向名为 struct list 的某个东西的指针,而这与当前正在定义的结构类型无关。请注意,使用 typedef struct { struct asdfasdf *next; } list; 同样“有效”。 - Nate Eldredge
我明白了,如果我使用后者,那么 struct list* 就会成为与外部的 list 相同类型的类型? - Dan
1个回答

5

首先,你的问题中并没有匿名结构体。这里有一些未命名结构体的示例。

匿名结构体的概念在C标准中的定义如下(6.7.2.1 结构体和联合体说明):

13 没有标记的结构体类型的未命名成员称为匿名结构体; 没有标记的联合体类型的未命名成员称为匿名联合体。匿名结构体或联合体的成员被视为包含结构体或联合体的成员。如果包含结构体或联合体也是匿名的,则递归应用此规则。

至于这个声明:

typedef struct {
    struct list *next;
} list;

然后声明了两种不同的类型:命名为 list 的无名结构体别名以及类型 struct list 的不完全声明。 liststruct list 是两种不同的不兼容类型。

例如,如果您尝试运行这个简单的程序:

#include <stdio.h>

typedef struct {
    struct list *next;
} list;

int main(void) 
{
    list lst1;
    list lst2;
    
    lst1.next = &lst2;
    
    return 0;
}

如果出现这个语句,编译器会报错。

lst1.next = &lst2;

报错提示为“无法从不兼容的指针类型'list *'赋值给结构体列表指针'struct list *'。”


我认为没有名称的结构体被称为“匿名”的,那么未命名和匿名有什么区别呢? - Dan
谢谢,我只是想澄清一下,这是前向声明吗?将指针指向一个尚不存在的 struct list(在结构体内部)? - Dan
@Dan 是的,你可以声明一个指向不完整类型的指针。 - Vlad from Moscow
具体称为前向声明的是什么? - Dan
@Dan 是的,它可以被视为前向声明。 - Vlad from Moscow

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接