简体   繁体   English

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

[英]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 ) (在GCCMSVC工作)

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 ElementElement不是同一个东西)。 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.

相关问题 为什么这个C代码编译? C struct typdef - Why does this C code compile? C struct typdef 为什么包含结构指针成员的结构编译但包含简单结构成员的结构不编译 - Why a structure containing a struct pointer member compile but containing a simple struct member does not compile 当我编译内核时,是什么导致这个奇怪的警告? 传递不兼容的指针类型,期望的struct *但得到struct * - What's Causing This Strange Warning When I Compile My Kernel? Passing incompatible pointer type, expected struct * but got struct * 将结构的地址分配给指针 - assign struct's address to pointer 指向结构的指针成员 - Pointing struct's pointer member 您能否使用指向包含结构的指针来修改嵌套结构的值? - Can you modify a nested struct's value using a pointer to the containing struct? 要从C中的结构内存访问类型的结构指针数据 - Want to access struct pointer's data of type from struct's memory in C 有什么区别:使用关键字 struct 在相同类型的结构内创建结构指针 - What's the difference: Creating structure pointer inside a structure of the same type with the keyword struct Struct条目声明了一个数组类型的字段,但是编译器说这是一个指针 - Struct entry declares a field of type array, but compiler says it's a pointer Struct对类型大小的贡献 - Struct's contribution to type size
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM