为什么"typdef struct {struct S*s;} S;" 包含指向同一类型的指针编译?

ord*_*dag 22 c struct typedef

我想typedef一个struct其中包含一个指向另一个相同类型的.

多数民众赞成我认为最好的版本:

typedef struct Element
{
    char value;
    struct Element *next;
} Element;
Run Code Online (Sandbox Code Playgroud)

为什么该变体也在编译+执行?:

typedef struct
{
    char value;
    struct Element *next;
} Element;
Run Code Online (Sandbox Code Playgroud)

为了描述第一个我会说:" struct Element Element现在名字",第二个:"匿名struct并称之为Element"

但为什么我仍然可以在第二种情况下声明struct Element (在结构内)

(在GCC和工作MSVC)

Kei*_*son 23

在第一种情况下,您的结构有两个等效名称:( struct Element其中Element是struct标记)和Element(其中Elementtypedef是现有类型的别名).

在第二种情况下,您只是没有为结构定义标记.通常情况下这是完全有效的,但在这里你指struct Element的是next成员声明中不存在的类型.

在这种情况下,struct Element是一种不完整的类型.您不能声明不完整类型的对象,但可以声明指向它们的指针.

声明

typedef struct
{
    char value;
    struct Element *next;
} Element;
Run Code Online (Sandbox Code Playgroud)

是合法的,但它不会next指向封闭类型.它使它成为指向某些不完整类型的指针,除非您声明完整类型,否则您将无法引用它.

你的第二个宣言是众多没有意义的事情之一,但仍然是合法的.

可以考虑省略typedef并始终将类型称为struct Element.很多人都喜欢为结构类型设置单字名称的便利,但我个人的意见是,没有太多的好处(除非类型真的不透明,即类型的用户甚至不知道它是一个结构).这是一种风格问题.

请注意,您需要在定义本身中引用类型struct Element,而不是Element,因为typedef名称Element尚不可见.

struct标签和typedef具有相同名称的事实可能看起来令人困惑,但它完全合法.struct标签和typedef位于不同的命名空间中(在C意义上,而不是C++意义上); 结构标记只能在struct关键字后面立即出现.

另一种方法是将typedef与struct定义分开:

typedef struct Element Element;

struct Element {
    char value;
    Element *next;
};
Run Code Online (Sandbox Code Playgroud)

(您可以在typedef.中使用不完整的类型名称.)