[英]Why does “typdef struct { struct S *s; } S;” containing a pointer to same type compile?
I'm trying to typedef
a struct
which contains a pointer to another of the same type. 我想
typedef
一个struct
包含一个指向另一个相同类型的。
Thats what I thought would be the best version: 多数民众赞成我认为最好的版本:
typedef struct Element
{
char value;
struct Element *next;
} Element;
Why is that variant also compiling + executing?: 为什么该变体也在编译+执行?:
typedef struct
{
char value;
struct Element *next;
} Element;
To describe the first I'd say: "Name struct Element
Element
now" and the second as: "Take this anonymous struct
and call it Element
" 要描述第一个我会说: “现在名字
struct Element
Element
” ,第二个作为: “取这个匿名struct
并称之为Element
”
But why can I still declare a struct Element
(inside the struct) in the second case? 但是为什么我仍然可以在第二种情况下声明一个
struct Element
(在struct中) ?
(Working in GCC
and MSVC
) (在
GCC
和MSVC
工作)
In the first case, your struct has two equivalent names: struct Element
(where Element
is a struct tag) and Element
(where Element
is a typedef, an alias for an existing type). 在第一种情况下,您的结构有两个等效名称:
struct Element
(其中Element
是结构标记)和Element
(其中Element
是typedef,现有类型的别名)。
In the second case, you just didn't define a tag for the struct. 在第二种情况下,您只是没有为结构定义标记。 Normally that would be perfectly valid, but here you're referring to the nonexistent type
struct Element
in the declaration of the next
member. 通常情况下这是完全有效的,但在这里你指的是
next
成员的声明中不存在的类型struct Element
。
In that context, struct Element
is an incomplete type . 在该上下文中,
struct Element
是不完整的类型 。 You can't declare objects of incomplete types, but you can declare pointers to them. 您不能声明不完整类型的对象,但可以声明指向它们的指针。
The declaration 声明
typedef struct
{
char value;
struct Element *next;
} Element;
is legal, but it doesn't make next
a pointer to the enclosing type. 是合法的,但它不会使
next
一个指向封闭类型的指针。 It makes it a pointer to some incomplete type, and you won't be able to refer to it until and unless you declare the full type. 它使它成为指向某些不完整类型的指针,除非您声明完整类型,否则您将无法引用它。
Your second declaration is one of the plethora of things that don't make sense, but are still legal C. 你的第二个宣言是众多没有意义的事情之一,但仍然是合法的。
You might consider just omitting the typedef and consistently referring to the type as struct Element
. 您可以考虑省略typedef并始终将类型称为
struct Element
。 As lot of people like the convenience of having a one-word name for a structure type, but my own personal opinion is that there's not much benefit to that (unless the type is truly opaque, ie, users of the type don't even know it's a struct). 很多人都喜欢为结构类型设置单字名称的便利,但我个人的意见是,没有太多的好处(除非类型真的不透明,即类型的用户甚至不知道它是一个结构)。 It's a matter of style.
这是一种风格问题。
Note that you need to refer to the type as struct Element
, not Element
, within the definition itself, since the typedef name Element
isn't visible yet. 请注意,您需要在定义本身中将类型称为
struct Element
而不是Element
,因为typedef名称Element
尚未可见。
The fact that the struct tag and the typedef have the same name may seem confusing, but it's perfectly legititimate. struct标签和typedef具有相同名称的事实可能看起来令人困惑,但它完全合法。 Struct tags and typedefs are in separate namespaces (in the C sense, not the C++ sense);
struct标签和typedef位于不同的命名空间中(在C意义上,而不是C ++意义上); a struct tag can only appear immediately after the
struct
keyword. struct标签只能在
struct
关键字后面立即出现。
Another alternative is to separate the typedef from the struct definition: 另一种方法是将typedef与struct定义分开:
typedef struct Element Element;
struct Element {
char value;
Element *next;
};
(You can use an incomplete type name in a typedef
.) (您可以在
typedef
使用不完整的类型名称。)
Your first variant is correct. 你的第一个变种是正确的。 Your second variant doesn't do what it appears to do.
你的第二个变种不会做它看起来做的事情。
In C, it's valid to forward-declare a struct type anywhere , even in the middle of declaring something else. 在C中,在任何地方向前声明结构类型是有效的,即使在声明其他内容的过程中也是如此。 (The scoping rules for such declarations-in-passing are confusing to the point where I'm not going to try to explain them -- suffice to say that you should avoid doing so.) That is why you don't get an error on the second construct.
(此类声明的范围规则令我感到困惑,我不打算解释它们 - 足以说明你应该避免这样做。)这就是为什么你没有得到错误在第二个结构上。 But what it means to the compiler is this:
但它对编译器意味着什么:
struct _Anonymous_1 // name not actually accessible to code
{
char value;
struct Element *next;
};
typedef struct _Anonymous_1 Element;
After this code, the type "struct Element" is completely unrelated to the type "Element", and has not been fully declared. 在此代码之后,类型“struct Element” 与 “Element”类型完全无关 ,并且尚未完全声明。 If you were to attempt to use that type, eg in
如果您尝试使用该类型,例如
char cadr(Element *cons)
{
return cons->next->value;
}
the compiler would not be happy: 编译器不会高兴:
test.c: In function ‘cadr’:
test.c:9:22: error: dereferencing pointer to incomplete type
An alternative to your first variant, that lets you use 'Element' instead of 'struct Element' everywhere, including inside the definition of the type, is 您的第一个变体的替代方案,允许您在任何地方使用“元素”而不是“结构元素”,包括在类型的定义内,
typedef struct Element Element;
struct Element
{
char value;
Element *next;
};
But in C there is no way to avoid having to manually make sure that "struct Element" is the same thing as "Element". 但是在C中没有办法避免必须手动确保“struct Element”与“Element”相同。 If you don't want to have to deal with it, C++ is waiting for you over there ⟶
如果你不想处理它,那么C ++就在那里等你
To store a pointer to a struct, the compiler doesn't need to know its contents or size -- just the size of the pointer. 要存储指向结构的指针,编译器不需要知道其内容或大小 - 只需指向指针的大小。
In your first example, struct Element
is an incomplete type until after the structure definition, but that works because you're only declaring a pointer to it and not an instance of the struct itself. 在您的第一个示例中,
struct Element
是一个不完整的类型,直到结构定义之后,但这是有效的,因为您只是声明指向它的指针而不是结构本身的实例。
In your second example, you don't declare a struct Element
structure at all ( struct Element
and Element
are not the same thing). 在第二个示例中,您根本不声明
struct Element
结构( struct Element
和Element
不是同一个东西)。 Though you can still include the pointer in the structure, it does NOT refer to the same type, it refers to a struct Element
that hasn't been defined. 虽然您仍然可以在结构中包含指针,但它不引用相同的类型,它指的是尚未定义的
struct Element
。 The struct definition in your typedef is an anonymous struct, so you'll be able to refer to it with Element
(without the struct keyword) only. typedef中的struct定义是一个匿名结构,因此您只能使用
Element
(不带struct关键字)来引用它。 So the second example won't work as intended. 所以第二个例子不会按预期工作。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.