繁体   English   中英

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

[英]Why does “typdef struct { struct S *s; } S;” containing a pointer to same type compile?

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

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

typedef struct Element
{
    char value;
    struct Element *next;
} Element;

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

typedef struct
{
    char value;
    struct Element *next;
} Element;

要描述第一个我会说: “现在名字struct Element Element ,第二个作为: “取这个匿名struct并称之为Element

但是为什么我仍然可以在第二种情况下声明一个struct Element (在struct中)

(在GCCMSVC工作)

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

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

在该上下文中, struct Element不完整的类型 您不能声明不完整类型的对象,但可以声明指向它们的指针。

声明

typedef struct
{
    char value;
    struct Element *next;
} Element;

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

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

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

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

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

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

typedef struct Element Element;

struct Element {
    char value;
    Element *next;
};

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

你的第一个变种是正确的。 你的第二个变种不会做它看起来做的事情。

在C中,在任何地方向前声明结构类型是有效的,即使在声明其他内容的过程中也是如此。 (此类声明的范围规则令我感到困惑,我不打算解释它们 - 足以说明你应该避免这样做。)这就是为什么你没有得到错误在第二个结构上。 但它对编译器意味着什么:

struct _Anonymous_1 // name not actually accessible to code
{
    char value;
    struct Element *next;
};
typedef struct _Anonymous_1 Element;

在此代码之后,类型“struct Element” “Element”类型完全无关 ,并且尚未完全声明。 如果您尝试使用该类型,例如

char cadr(Element *cons)
{
    return cons->next->value;
}

编译器不会高兴:

test.c: In function ‘cadr’:
test.c:9:22: error: dereferencing pointer to incomplete type

您的第一个变体的替代方案,允许您在任何地方使用“元素”而不是“结构元素”,包括在类型的定义内,

typedef struct Element Element;
struct Element
{
    char value;
    Element *next;
};

但是在C中没有办法避免必须手动确保“struct Element”与“Element”相同。 如果你不想处理它,那么C ++就在那里等你

要存储指向结构的指针,编译器不需要知道其内容或大小 - 只需指向指针的大小。

在您的第一个示例中, struct Element是一个不完整的类型,直到结构定义之后,但这是有效的,因为您只是声明指向它的指针而不是结构本身的实例。

在第二个示例中,您根本不声明struct Element结构( struct ElementElement不是同一个东西)。 虽然您仍然可以在结构中包含指针,但它不引用相同的类型,它指的是尚未定义的struct Element typedef中的struct定义是一个匿名结构,因此您只能使用Element (不带struct关键字)来引用它。 所以第二个例子不会按预期工作。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM