[英]Why is `typedef struct x x` allowed?
I was reading the book modern C and was suprised to find that the following code works 我正在阅读《 现代C》这本书,很惊讶地发现以下代码有效
typedef struct point point;
struct point {
int x;
int y;
};
int main() {
point p = { .x = 1, .y = 2 };
}
However, the book does not go in detail about that. 但是,这本书没有详细介绍。 How does that work?
这是如何运作的? Why does
point
in main()
refer to the typedef
since struct point
is defined after that? 为什么
main()
中的point
引用typedef
因为struct point
是在此之后定义的?
The line typedef struct point point;
线
typedef struct point point;
does two things: 做两件事:
struct point
struct point
的前向声明 struct point
called point
. point
struct point
创建类型别名。 Forward declarations are useful if you need to know a struct exits before it is fully defined, for example: 如果您需要在结构完全定义之前就知道其退出,则前向声明很有用,例如:
typedef struct x X;
typedef struct y {
int a;
X *x;
} Y;
struct x {
int b;
Y *y;
};
You can use struct foo
in many places before struct foo { ... }
is defined. 在定义
struct foo { ... }
之前,可以在许多地方使用struct foo
。 This is known as an "incomplete type". 这称为“不完整类型”。
It's useful because it lets you define abstract types: 这很有用,因为它使您可以定义抽象类型:
foo_header.h foo_header.h
struct foo; // abstract
struct foo *foo_create(void);
void do_stuff_with(struct foo *);
void foo_destroy(struct foo *);
This way users of the library can use struct pointers and functions that work on these pointers without knowing how the struct is actually defined, which is nice for encapsulation. 这样,库的用户可以使用结构指针和在这些指针上工作的函数,而无需了解结构的实际定义方式,这对于封装非常有用。
It's also used in recursive types: 它也用于递归类型:
struct node {
int data;
struct node *next; // struct node isn't defined yet!
};
// here the definition of struct node is complete
C supports it because it's easy to implement: To compile code that uses struct foo *
, the compiler only has to know how big the pointer is. C支持它,因为它易于实现:要编译使用
struct foo *
代码,编译器只需知道指针的大小即可。 It doesn't care about the struct members. 它不在乎结构成员。
Similarly, in your typedef
example, the compiler doesn't need to know the details of the struct to create a type alias for it. 同样,在您的
typedef
示例中,编译器不需要知道结构的详细信息即可为其创建类型别名。
This works because C has multiple name spaces : 之所以可行,是因为C具有多个名称空间 :
goto
or trailing :
); goto
或尾随:
); struct
, enum
, and union
(disambiguated by the struct
, union
, or enum
keywords): struct
, enum
和union
标记名称(由struct
, union
或enum
关键字消除歧义): struct
and union
members (disambiguated by a leading .
or ->
, each struct
or union
type acts as its own namespace, so different struct
and union
types can use the same member names); struct
和union
成员的名称(由前导.
或->
消除歧义,每个struct
或union
类型都充当其自己的名称空间,因此不同的struct
和union
类型可以使用相同的成员名称); So you can use the same name as a label, a tag name, a member name, and a regular identifier all in the same code, and the compiler is able to distinguish between them: 因此,您可以在同一代码中使用与标签相同的名称,标签名称,成员名称和常规标识符,并且编译器可以区分它们:
struct x { int x; }; // tag name, member name
void foo( struct x x ) // tag name, all other identifiers
{
if ( x.x ) // all other identifiers, member name
goto x; // label name
// do something here
x: printf( "At label x\n" ); // label name
}
This example comes straight from C standard, Section 6.7.2.3: 此示例直接来自C标准的6.7.2.3节:
The following alternative formulation uses the typedef mechanism:
以下替代公式使用typedef机制:
typedef struct tnode TNODE;
struct tnode {
int count;
TNODE *left, *right;
};
TNODE s, *sp;
What it does it forward declares struct, and than creates a type alias for it. 它向前执行的操作将声明struct,然后为其创建类型别名。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.